localstack-core 4.7.1.dev96__py3-none-any.whl → 4.7.1.dev97__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of localstack-core might be problematic. Click here for more details.

Files changed (65) hide show
  1. localstack/aws/mocking.py +2 -2
  2. localstack/aws/protocol/parser.py +6 -6
  3. localstack/aws/protocol/serializer.py +5 -5
  4. localstack/aws/scaffold.py +1 -1
  5. localstack/cli/localstack.py +1 -1
  6. localstack/cli/plugins.py +1 -1
  7. localstack/config.py +5 -5
  8. localstack/dev/run/configurators.py +1 -4
  9. localstack/runtime/hooks.py +1 -1
  10. localstack/runtime/init.py +1 -1
  11. localstack/runtime/main.py +5 -5
  12. localstack/services/apigateway/helpers.py +1 -4
  13. localstack/services/apigateway/legacy/helpers.py +7 -8
  14. localstack/services/apigateway/legacy/integration.py +4 -3
  15. localstack/services/apigateway/legacy/invocations.py +2 -2
  16. localstack/services/apigateway/legacy/provider.py +4 -4
  17. localstack/services/apigateway/resource_providers/aws_apigateway_resource.py +1 -1
  18. localstack/services/cloudformation/api_utils.py +4 -8
  19. localstack/services/cloudformation/cfn_utils.py +1 -1
  20. localstack/services/cloudformation/engine/entities.py +1 -2
  21. localstack/services/cloudformation/engine/template_deployer.py +2 -2
  22. localstack/services/cloudformation/engine/v2/change_set_model_transform.py +2 -2
  23. localstack/services/cloudformation/provider.py +2 -2
  24. localstack/services/cloudformation/service_models.py +1 -1
  25. localstack/services/dynamodb/server.py +1 -1
  26. localstack/services/edge.py +1 -1
  27. localstack/services/events/v1/provider.py +5 -5
  28. localstack/services/kinesis/provider.py +1 -1
  29. localstack/services/plugins.py +6 -6
  30. localstack/services/ssm/provider.py +1 -1
  31. localstack/state/pickle.py +1 -1
  32. localstack/testing/pytest/fixtures.py +3 -3
  33. localstack/utils/analytics/metadata.py +1 -1
  34. localstack/utils/aws/arns.py +7 -20
  35. localstack/utils/aws/aws_responses.py +1 -1
  36. localstack/utils/aws/dead_letter_queue.py +1 -5
  37. localstack/utils/aws/resources.py +1 -1
  38. localstack/utils/aws/templating.py +1 -1
  39. localstack/utils/bootstrap.py +4 -4
  40. localstack/utils/container_utils/docker_cmd_client.py +19 -19
  41. localstack/utils/crypto.py +10 -10
  42. localstack/utils/diagnose.py +1 -1
  43. localstack/utils/files.py +2 -6
  44. localstack/utils/functions.py +1 -1
  45. localstack/utils/http.py +5 -5
  46. localstack/utils/net.py +3 -2
  47. localstack/utils/objects.py +1 -1
  48. localstack/utils/run.py +2 -2
  49. localstack/utils/serving.py +1 -1
  50. localstack/utils/strings.py +5 -5
  51. localstack/utils/testutil.py +3 -4
  52. localstack/utils/time.py +1 -1
  53. localstack/utils/xray/traceid.py +1 -1
  54. localstack/version.py +2 -2
  55. {localstack_core-4.7.1.dev96.dist-info → localstack_core-4.7.1.dev97.dist-info}/METADATA +1 -1
  56. {localstack_core-4.7.1.dev96.dist-info → localstack_core-4.7.1.dev97.dist-info}/RECORD +64 -64
  57. localstack_core-4.7.1.dev97.dist-info/plux.json +1 -0
  58. localstack_core-4.7.1.dev96.dist-info/plux.json +0 -1
  59. {localstack_core-4.7.1.dev96.data → localstack_core-4.7.1.dev97.data}/scripts/localstack +0 -0
  60. {localstack_core-4.7.1.dev96.data → localstack_core-4.7.1.dev97.data}/scripts/localstack-supervisor +0 -0
  61. {localstack_core-4.7.1.dev96.data → localstack_core-4.7.1.dev97.data}/scripts/localstack.bat +0 -0
  62. {localstack_core-4.7.1.dev96.dist-info → localstack_core-4.7.1.dev97.dist-info}/WHEEL +0 -0
  63. {localstack_core-4.7.1.dev96.dist-info → localstack_core-4.7.1.dev97.dist-info}/entry_points.txt +0 -0
  64. {localstack_core-4.7.1.dev96.dist-info → localstack_core-4.7.1.dev97.dist-info}/licenses/LICENSE.txt +0 -0
  65. {localstack_core-4.7.1.dev96.dist-info → localstack_core-4.7.1.dev97.dist-info}/top_level.txt +0 -0
@@ -64,7 +64,7 @@ def register(cls: type = None, subclasses: bool = False):
64
64
  elif callable(fn):
65
65
  add_dispatch_entry(cls, fn, subclasses=subclasses)
66
66
  else:
67
- raise ValueError("cannot register %s" % fn)
67
+ raise ValueError(f"cannot register {fn}")
68
68
 
69
69
  return fn
70
70
 
@@ -232,7 +232,7 @@ def s3_create_bucket(s3_empty_bucket, aws_client):
232
232
 
233
233
  def factory(**kwargs) -> str:
234
234
  if "Bucket" not in kwargs:
235
- kwargs["Bucket"] = "test-bucket-%s" % short_uid()
235
+ kwargs["Bucket"] = f"test-bucket-{short_uid()}"
236
236
 
237
237
  if (
238
238
  "CreateBucketConfiguration" not in kwargs
@@ -335,7 +335,7 @@ def sqs_create_queue(aws_client):
335
335
 
336
336
  def factory(**kwargs):
337
337
  if "QueueName" not in kwargs:
338
- kwargs["QueueName"] = "test-queue-%s" % short_uid()
338
+ kwargs["QueueName"] = f"test-queue-{short_uid()}"
339
339
 
340
340
  response = aws_client.sqs.create_queue(**kwargs)
341
341
  url = response["QueueUrl"]
@@ -503,7 +503,7 @@ def sns_create_topic(aws_client):
503
503
 
504
504
  def _create_topic(**kwargs):
505
505
  if "Name" not in kwargs:
506
- kwargs["Name"] = "test-topic-%s" % short_uid()
506
+ kwargs["Name"] = f"test-topic-{short_uid()}"
507
507
  response = aws_client.sns.create_topic(**kwargs)
508
508
  topic_arns.append(response["TopicArn"])
509
509
  return response
@@ -41,7 +41,7 @@ class ClientMetadata:
41
41
  k = "*" * len(k)
42
42
  d["api_key"] = k
43
43
 
44
- return "ClientMetadata(%s)" % d
44
+ return f"ClientMetadata({d})"
45
45
 
46
46
 
47
47
  def get_version_string() -> str:
@@ -120,7 +120,7 @@ def iam_role_arn(role_name: str, account_id: str, region_name: str) -> str:
120
120
  return role_name
121
121
  if re.match(f"{ARN_PARTITION_REGEX}:iam::", role_name):
122
122
  return role_name
123
- return "arn:%s:iam::%s:role/%s" % (get_partition(region_name), account_id, role_name)
123
+ return f"arn:{get_partition(region_name)}:iam::{account_id}:role/{role_name}"
124
124
 
125
125
 
126
126
  def iam_resource_arn(resource: str, account_id: str, role: str = None) -> str:
@@ -180,13 +180,7 @@ def dynamodb_table_arn(table_name: str, account_id: str, region_name: str) -> st
180
180
  def dynamodb_stream_arn(
181
181
  table_name: str, latest_stream_label: str, account_id: str, region_name: str
182
182
  ) -> str:
183
- return "arn:%s:dynamodb:%s:%s:table/%s/stream/%s" % (
184
- get_partition(region_name),
185
- region_name,
186
- account_id,
187
- table_name,
188
- latest_stream_label,
189
- )
183
+ return f"arn:{get_partition(region_name)}:dynamodb:{region_name}:{account_id}:table/{table_name}/stream/{latest_stream_label}"
190
184
 
191
185
 
192
186
  #
@@ -453,7 +447,7 @@ def s3_bucket_arn(bucket_name_or_arn: str, region="us-east-1") -> str:
453
447
 
454
448
  def sqs_queue_arn(queue_name: str, account_id: str, region_name: str) -> str:
455
449
  queue_name = queue_name.split("/")[-1]
456
- return "arn:%s:sqs:%s:%s:%s" % (get_partition(region_name), region_name, account_id, queue_name)
450
+ return f"arn:{get_partition(region_name)}:sqs:{region_name}:{account_id}:{queue_name}"
457
451
 
458
452
 
459
453
  #
@@ -462,20 +456,13 @@ def sqs_queue_arn(queue_name: str, account_id: str, region_name: str) -> str:
462
456
 
463
457
 
464
458
  def apigateway_restapi_arn(api_id: str, account_id: str, region_name: str) -> str:
465
- return "arn:%s:apigateway:%s:%s:/restapis/%s" % (
466
- get_partition(region_name),
467
- region_name,
468
- account_id,
469
- api_id,
459
+ return (
460
+ f"arn:{get_partition(region_name)}:apigateway:{region_name}:{account_id}:/restapis/{api_id}"
470
461
  )
471
462
 
472
463
 
473
464
  def apigateway_invocations_arn(lambda_uri: str, region_name: str) -> str:
474
- return "arn:%s:apigateway:%s:lambda:path/2015-03-31/functions/%s/invocations" % (
475
- get_partition(region_name),
476
- region_name,
477
- lambda_uri,
478
- )
465
+ return f"arn:{get_partition(region_name)}:apigateway:{region_name}:lambda:path/2015-03-31/functions/{lambda_uri}/invocations"
479
466
 
480
467
 
481
468
  #
@@ -555,7 +542,7 @@ def lambda_function_name(name_or_arn: str) -> str:
555
542
  if ":" in name_or_arn:
556
543
  arn = parse_arn(name_or_arn)
557
544
  if arn["service"] != "lambda":
558
- raise ValueError("arn is not a lambda arn %s" % name_or_arn)
545
+ raise ValueError(f"arn is not a lambda arn {name_or_arn}")
559
546
 
560
547
  return parse_arn(name_or_arn)["resource"].split(":")[1]
561
548
  else:
@@ -42,7 +42,7 @@ def requests_error_response_xml(
42
42
  xmlns: Optional[str] = None,
43
43
  ):
44
44
  response = RequestsResponse()
45
- xmlns = xmlns or "http://%s.amazonaws.com/doc/2010-03-31/" % service
45
+ xmlns = xmlns or f"http://{service}.amazonaws.com/doc/2010-03-31/"
46
46
  response._content = f"""<ErrorResponse xmlns="{xmlns}"><Error>
47
47
  <Type>Sender</Type>
48
48
  <Code>{code_string}</Code>
@@ -59,11 +59,7 @@ def _send_to_dead_letter_queue(source_arn: str, dlq_arn: str, event: dict, error
59
59
  except Exception as e:
60
60
  error = e
61
61
  if error or not result_code or result_code >= 400:
62
- msg = "Unable to send message to dead letter queue %s (code %s): %s" % (
63
- queue_url,
64
- result_code,
65
- error,
66
- )
62
+ msg = f"Unable to send message to dead letter queue {queue_url} (code {result_code}): {error}"
67
63
  if "InvalidMessageContents" in str(error):
68
64
  msg += f" - messages: {messages}"
69
65
  LOG.info(msg)
@@ -86,7 +86,7 @@ def create_api_gateway(
86
86
  resources = resources or []
87
87
  stage_name = stage_name or "testing"
88
88
  usage_plan_name = usage_plan_name or "Basic Usage"
89
- description = description or 'Test description for API "%s"' % name
89
+ description = description or f'Test description for API "{name}"'
90
90
 
91
91
  LOG.info('Creating API resources under API Gateway "%s".', name)
92
92
  api = client.create_rest_api(name=name, description=description)
@@ -66,7 +66,7 @@ class VtlTemplate:
66
66
  empty_placeholder = " __pLaCe-HoLdEr__ "
67
67
  template = re.sub(
68
68
  r"([^\s]+)#\$({)?(.*)",
69
- r"\1#%s$\2\3" % empty_placeholder,
69
+ rf"\1#{empty_placeholder}$\2\3",
70
70
  template,
71
71
  count=re.MULTILINE,
72
72
  )
@@ -427,7 +427,7 @@ def validate_localstack_config(name: str):
427
427
 
428
428
  def port_exposed(port):
429
429
  for exposed in docker_ports:
430
- if re.match(r"^([0-9]+-)?%s(-[0-9]+)?$" % port, exposed):
430
+ if re.match(rf"^([0-9]+-)?{port}(-[0-9]+)?$", exposed):
431
431
  return True
432
432
 
433
433
  if not port_exposed(edge_port):
@@ -455,7 +455,7 @@ def get_docker_image_to_start():
455
455
 
456
456
  def extract_port_flags(user_flags, port_mappings: PortMappings):
457
457
  regex = r"-p\s+([0-9]+)(\-([0-9]+))?:([0-9]+)(\-([0-9]+))?"
458
- matches = re.match(".*%s" % regex, user_flags)
458
+ matches = re.match(f".*{regex}", user_flags)
459
459
  if matches:
460
460
  for match in re.findall(regex, user_flags):
461
461
  start = int(match[0])
@@ -1115,7 +1115,7 @@ class LocalstackContainerServer(Server):
1115
1115
  def do_run(self):
1116
1116
  if self.is_container_running():
1117
1117
  raise ContainerExists(
1118
- 'LocalStack container named "%s" is already running' % self.container.name
1118
+ f'LocalStack container named "{self.container.name}" is already running'
1119
1119
  )
1120
1120
 
1121
1121
  config.dirs.mkdirs()
@@ -1156,7 +1156,7 @@ def prepare_docker_start():
1156
1156
  container_name = config.MAIN_CONTAINER_NAME
1157
1157
 
1158
1158
  if DOCKER_CLIENT.is_container_running(container_name):
1159
- raise ContainerExists('LocalStack container named "%s" is already running' % container_name)
1159
+ raise ContainerExists(f'LocalStack container named "{container_name}" is already running')
1160
1160
 
1161
1161
  config.dirs.mkdirs()
1162
1162
 
@@ -202,7 +202,7 @@ class CmdDockerClient(ContainerClient):
202
202
  except subprocess.CalledProcessError as e:
203
203
  self._check_and_raise_no_such_container_error(container_name, error=e)
204
204
  raise ContainerException(
205
- "Docker process returned with errorcode %s" % e.returncode, e.stdout, e.stderr
205
+ f"Docker process returned with errorcode {e.returncode}", e.stdout, e.stderr
206
206
  ) from e
207
207
 
208
208
  def pause_container(self, container_name: str) -> None:
@@ -214,7 +214,7 @@ class CmdDockerClient(ContainerClient):
214
214
  except subprocess.CalledProcessError as e:
215
215
  self._check_and_raise_no_such_container_error(container_name, error=e)
216
216
  raise ContainerException(
217
- "Docker process returned with errorcode %s" % e.returncode, e.stdout, e.stderr
217
+ f"Docker process returned with errorcode {e.returncode}", e.stdout, e.stderr
218
218
  ) from e
219
219
 
220
220
  def unpause_container(self, container_name: str) -> None:
@@ -226,7 +226,7 @@ class CmdDockerClient(ContainerClient):
226
226
  except subprocess.CalledProcessError as e:
227
227
  self._check_and_raise_no_such_container_error(container_name, error=e)
228
228
  raise ContainerException(
229
- "Docker process returned with errorcode %s" % e.returncode, e.stdout, e.stderr
229
+ f"Docker process returned with errorcode {e.returncode}", e.stdout, e.stderr
230
230
  ) from e
231
231
 
232
232
  def remove_image(self, image: str, force: bool = True) -> None:
@@ -243,7 +243,7 @@ class CmdDockerClient(ContainerClient):
243
243
  if any(msg in to_str(e.stdout) for msg in error_messages):
244
244
  raise NoSuchImage(image, stdout=e.stdout, stderr=e.stderr)
245
245
  raise ContainerException(
246
- "Docker process returned with errorcode %s" % e.returncode, e.stdout, e.stderr
246
+ f"Docker process returned with errorcode {e.returncode}", e.stdout, e.stderr
247
247
  ) from e
248
248
 
249
249
  def commit(
@@ -262,7 +262,7 @@ class CmdDockerClient(ContainerClient):
262
262
  except subprocess.CalledProcessError as e:
263
263
  self._check_and_raise_no_such_container_error(container_name_or_id, error=e)
264
264
  raise ContainerException(
265
- "Docker process returned with errorcode %s" % e.returncode, e.stdout, e.stderr
265
+ f"Docker process returned with errorcode {e.returncode}", e.stdout, e.stderr
266
266
  ) from e
267
267
 
268
268
  def remove_container(self, container_name: str, force=True, check_existence=False) -> None:
@@ -282,7 +282,7 @@ class CmdDockerClient(ContainerClient):
282
282
  if not force:
283
283
  self._check_and_raise_no_such_container_error(container_name, error=e)
284
284
  raise ContainerException(
285
- "Docker process returned with errorcode %s" % e.returncode, e.stdout, e.stderr
285
+ f"Docker process returned with errorcode {e.returncode}", e.stdout, e.stderr
286
286
  ) from e
287
287
 
288
288
  def list_containers(self, filter: Union[list[str], str, None] = None, all=True) -> list[dict]:
@@ -301,7 +301,7 @@ class CmdDockerClient(ContainerClient):
301
301
  cmd_result = run(cmd).strip()
302
302
  except subprocess.CalledProcessError as e:
303
303
  raise ContainerException(
304
- "Docker process returned with errorcode %s" % e.returncode, e.stdout, e.stderr
304
+ f"Docker process returned with errorcode {e.returncode}", e.stdout, e.stderr
305
305
  ) from e
306
306
  container_list = []
307
307
  if cmd_result:
@@ -355,7 +355,7 @@ class CmdDockerClient(ContainerClient):
355
355
  if re.match(".*container .+ does not exist", to_str(e.stdout)):
356
356
  raise NoSuchContainer(container_name, stdout=e.stdout, stderr=e.stderr)
357
357
  raise ContainerException(
358
- "Docker process returned with errorcode %s" % e.returncode, e.stdout, e.stderr
358
+ f"Docker process returned with errorcode {e.returncode}", e.stdout, e.stderr
359
359
  ) from e
360
360
 
361
361
  def pull_image(
@@ -384,7 +384,7 @@ class CmdDockerClient(ContainerClient):
384
384
  if "Trying to pull" in stdout_str and "access to the resource is denied" in stdout_str:
385
385
  raise NoSuchImage(docker_image, stdout=e.stdout, stderr=e.stderr)
386
386
  raise ContainerException(
387
- "Docker process returned with errorcode %s" % e.returncode, e.stdout, e.stderr
387
+ f"Docker process returned with errorcode {e.returncode}", e.stdout, e.stderr
388
388
  ) from e
389
389
 
390
390
  def push_image(self, docker_image: str) -> None:
@@ -478,7 +478,7 @@ class CmdDockerClient(ContainerClient):
478
478
  return ""
479
479
  self._check_and_raise_no_such_container_error(container_name_or_id, error=e)
480
480
  raise ContainerException(
481
- "Docker process returned with errorcode %s" % e.returncode, e.stdout, e.stderr
481
+ f"Docker process returned with errorcode {e.returncode}", e.stdout, e.stderr
482
482
  ) from e
483
483
 
484
484
  def stream_container_logs(self, container_name_or_id: str) -> CancellableStream:
@@ -503,7 +503,7 @@ class CmdDockerClient(ContainerClient):
503
503
  if "no such object" in to_str(e.stdout).lower():
504
504
  raise NoSuchObject(object_name_or_id, stdout=e.stdout, stderr=e.stderr)
505
505
  raise ContainerException(
506
- "Docker process returned with errorcode %s" % e.returncode, e.stdout, e.stderr
506
+ f"Docker process returned with errorcode {e.returncode}", e.stdout, e.stderr
507
507
  ) from e
508
508
  object_data = json.loads(cmd_result.strip())
509
509
  if isinstance(object_data, list):
@@ -556,7 +556,7 @@ class CmdDockerClient(ContainerClient):
556
556
  return run(cmd).strip()
557
557
  except subprocess.CalledProcessError as e:
558
558
  raise ContainerException(
559
- "Docker process returned with errorcode %s" % e.returncode, e.stdout, e.stderr
559
+ f"Docker process returned with errorcode {e.returncode}", e.stdout, e.stderr
560
560
  ) from e
561
561
 
562
562
  def delete_network(self, network_name: str) -> None:
@@ -570,7 +570,7 @@ class CmdDockerClient(ContainerClient):
570
570
  raise NoSuchNetwork(network_name=network_name)
571
571
  else:
572
572
  raise ContainerException(
573
- "Docker process returned with errorcode %s" % e.returncode, e.stdout, e.stderr
573
+ f"Docker process returned with errorcode {e.returncode}", e.stdout, e.stderr
574
574
  ) from e
575
575
 
576
576
  def inspect_network(self, network_name: str) -> dict[str, Union[dict, str]]:
@@ -607,7 +607,7 @@ class CmdDockerClient(ContainerClient):
607
607
  raise NoSuchNetwork(network_name=network_name)
608
608
  self._check_and_raise_no_such_container_error(container_name_or_id, error=e)
609
609
  raise ContainerException(
610
- "Docker process returned with errorcode %s" % e.returncode, e.stdout, e.stderr
610
+ f"Docker process returned with errorcode {e.returncode}", e.stdout, e.stderr
611
611
  ) from e
612
612
 
613
613
  def disconnect_container_from_network(
@@ -625,7 +625,7 @@ class CmdDockerClient(ContainerClient):
625
625
  raise NoSuchNetwork(network_name=network_name)
626
626
  self._check_and_raise_no_such_container_error(container_name_or_id, error=e)
627
627
  raise ContainerException(
628
- "Docker process returned with errorcode %s" % e.returncode, e.stdout, e.stderr
628
+ f"Docker process returned with errorcode {e.returncode}", e.stdout, e.stderr
629
629
  ) from e
630
630
 
631
631
  def get_container_ip(self, container_name_or_id: str) -> str:
@@ -645,7 +645,7 @@ class CmdDockerClient(ContainerClient):
645
645
  if "no such object" in to_str(e.stdout).lower():
646
646
  raise NoSuchContainer(container_name_or_id, stdout=e.stdout, stderr=e.stderr)
647
647
  raise ContainerException(
648
- "Docker process returned with errorcode %s" % e.returncode, e.stdout, e.stderr
648
+ f"Docker process returned with errorcode {e.returncode}", e.stdout, e.stderr
649
649
  ) from e
650
650
 
651
651
  def login(self, username: str, password: str, registry: Optional[str] = None) -> None:
@@ -658,7 +658,7 @@ class CmdDockerClient(ContainerClient):
658
658
  run(cmd)
659
659
  except subprocess.CalledProcessError as e:
660
660
  raise ContainerException(
661
- "Docker process returned with errorcode %s" % e.returncode, e.stdout, e.stderr
661
+ f"Docker process returned with errorcode {e.returncode}", e.stdout, e.stderr
662
662
  ) from e
663
663
 
664
664
  @functools.cache
@@ -684,7 +684,7 @@ class CmdDockerClient(ContainerClient):
684
684
  if any(msg in to_str(e.stdout) for msg in error_messages):
685
685
  raise NoSuchImage(image_name, stdout=e.stdout, stderr=e.stderr)
686
686
  raise ContainerException(
687
- "Docker process returned with errorcode %s" % e.returncode, e.stdout, e.stderr
687
+ f"Docker process returned with errorcode {e.returncode}", e.stdout, e.stderr
688
688
  ) from e
689
689
  finally:
690
690
  Util.rm_env_vars_file(env_file)
@@ -791,7 +791,7 @@ class CmdDockerClient(ContainerClient):
791
791
  if any(msg.lower() in to_str(e.stderr).lower() for msg in error_messages):
792
792
  raise NoSuchContainer(container_name, stdout=e.stdout, stderr=e.stderr)
793
793
  raise ContainerException(
794
- "Docker process returned with errorcode %s" % e.returncode, e.stdout, e.stderr
794
+ f"Docker process returned with errorcode {e.returncode}", e.stdout, e.stderr
795
795
  ) from e
796
796
 
797
797
  def _build_run_create_cmd(
@@ -43,8 +43,8 @@ def generate_ssl_cert(
43
43
  return all(os.path.exists(f) for f in files)
44
44
 
45
45
  def store_cert_key_files(base_filename):
46
- key_file_name = "%s.key" % base_filename
47
- cert_file_name = "%s.crt" % base_filename
46
+ key_file_name = f"{base_filename}.key"
47
+ cert_file_name = f"{base_filename}.crt"
48
48
  # TODO: Cleaner code to load the cert dynamically
49
49
  # extract key and cert from target_file and store into separate files
50
50
  content = load_file(target_file)
@@ -74,9 +74,9 @@ def generate_ssl_cert(
74
74
  return target_file, cert_file_name, key_file_name
75
75
  if random and target_file:
76
76
  if "." in target_file:
77
- target_file = target_file.replace(".", ".%s." % short_uid(), 1)
77
+ target_file = target_file.replace(".", f".{short_uid()}.", 1)
78
78
  else:
79
- target_file = "%s.%s" % (target_file, short_uid())
79
+ target_file = f"{target_file}.{short_uid()}"
80
80
 
81
81
  # create a key pair
82
82
  k = crypto.PKey()
@@ -123,10 +123,10 @@ def generate_ssl_cert(
123
123
  key_file.write(to_str(crypto.dump_privatekey(crypto.FILETYPE_PEM, k)))
124
124
  cert_file_content = cert_file.getvalue().strip()
125
125
  key_file_content = key_file.getvalue().strip()
126
- file_content = "%s\n%s" % (key_file_content, cert_file_content)
126
+ file_content = f"{key_file_content}\n{cert_file_content}"
127
127
  if target_file:
128
- key_file_name = "%s.key" % target_file
129
- cert_file_name = "%s.crt" % target_file
128
+ key_file_name = f"{target_file}.key"
129
+ cert_file_name = f"{target_file}.crt"
130
130
  # check existence to avoid permission denied issues:
131
131
  # https://github.com/localstack/localstack/issues/1607
132
132
  if not all_exist(target_file, key_file_name, cert_file_name):
@@ -145,9 +145,9 @@ def generate_ssl_cert(
145
145
  e,
146
146
  )
147
147
  # Fix for https://github.com/localstack/localstack/issues/1743
148
- target_file = "%s.pem" % new_tmp_file()
149
- key_file_name = "%s.key" % target_file
150
- cert_file_name = "%s.crt" % target_file
148
+ target_file = f"{new_tmp_file()}.pem"
149
+ key_file_name = f"{target_file}.key"
150
+ cert_file_name = f"{target_file}.crt"
151
151
  TMP_FILES.append(target_file)
152
152
  TMP_FILES.append(key_file_name)
153
153
  TMP_FILES.append(cert_file_name)
@@ -134,7 +134,7 @@ def traverse_file_tree(root: str) -> list[str]:
134
134
  result.append(dirpath)
135
135
  return result
136
136
  except Exception as e:
137
- return ["traversing files failed %s" % e]
137
+ return [f"traversing files failed {e}"]
138
138
 
139
139
 
140
140
  def get_docker_image_details() -> dict[str, str]:
localstack/utils/files.py CHANGED
@@ -201,7 +201,7 @@ def rm_rf(path: str):
201
201
  # Running the native command can be an order of magnitude faster in Alpine on Travis-CI
202
202
  if is_debian():
203
203
  try:
204
- return run('rm -rf "%s"' % path)
204
+ return run(f'rm -rf "{path}"')
205
205
  except Exception:
206
206
  pass
207
207
  # Make sure all files are writeable and dirs executable to remove
@@ -247,11 +247,7 @@ def cp_r(src: str, dst: str, rm_dest_on_conflict=False, ignore_copystat_errors=F
247
247
  except Exception as e:
248
248
 
249
249
  def _info(_path):
250
- return "%s (file=%s, symlink=%s)" % (
251
- _path,
252
- os.path.isfile(_path),
253
- os.path.islink(_path),
254
- )
250
+ return f"{_path} (file={os.path.isfile(_path)}, symlink={os.path.islink(_path)})"
255
251
 
256
252
  LOG.debug("Error copying files from %s to %s: %s", _info(src), _info(dst), e)
257
253
  raise
@@ -32,7 +32,7 @@ def call_safe(
32
32
  :return: whatever the func returns
33
33
  """
34
34
  if exception_message is None:
35
- exception_message = "error calling function %s" % func.__name__
35
+ exception_message = f"error calling function {func.__name__}"
36
36
  if args is None:
37
37
  args = ()
38
38
  if kwargs is None:
localstack/utils/http.py CHANGED
@@ -43,12 +43,12 @@ def create_chunked_data(data, chunk_size: int = 80):
43
43
  dl = len(data)
44
44
  ret = ""
45
45
  for i in range(dl // chunk_size):
46
- ret += "%s\r\n" % (hex(chunk_size)[2:])
47
- ret += "%s\r\n\r\n" % (data[i * chunk_size : (i + 1) * chunk_size])
46
+ ret += f"{hex(chunk_size)[2:]}\r\n"
47
+ ret += f"{data[i * chunk_size : (i + 1) * chunk_size]}\r\n\r\n"
48
48
 
49
49
  if len(data) % chunk_size != 0:
50
- ret += "%s\r\n" % (hex(len(data) % chunk_size)[2:])
51
- ret += "%s\r\n" % (data[-(len(data) % chunk_size) :])
50
+ ret += f"{hex(len(data) % chunk_size)[2:]}\r\n"
51
+ ret += f"{data[-(len(data) % chunk_size) :]}\r\n"
52
52
 
53
53
  ret += "0\r\n\r\n"
54
54
  return ret
@@ -202,7 +202,7 @@ def download(
202
202
  r = s.get(url, stream=True, verify=_verify, timeout=timeout, headers=request_headers)
203
203
  # check status code before attempting to read body
204
204
  if not r.ok:
205
- raise Exception("Failed to download %s, response code %s" % (url, r.status_code))
205
+ raise Exception(f"Failed to download {url}, response code {r.status_code}")
206
206
 
207
207
  total_size = 0
208
208
  if r.headers.get("Content-Length"):
localstack/utils/net.py CHANGED
@@ -164,8 +164,9 @@ def wait_for_port_status(
164
164
  status = is_port_open(port, http_path=http_path, expect_success=expect_success)
165
165
  if bool(status) != (not expect_closed):
166
166
  raise Exception(
167
- "Port %s (path: %s) was not %s"
168
- % (port, http_path, "closed" if expect_closed else "open")
167
+ "Port {} (path: {}) was not {}".format(
168
+ port, http_path, "closed" if expect_closed else "open"
169
+ )
169
170
  )
170
171
 
171
172
  return retry(check, sleep=sleep_time, retries=retries)
@@ -163,7 +163,7 @@ def keys_to(
163
163
  skip_children_of = ensure_list(skip_children_of or [])
164
164
 
165
165
  def fix_keys(o, path="", **kwargs):
166
- if any(re.match(r"(^|.*\.)%s($|[.\[].*)" % k, path) for k in skip_children_of):
166
+ if any(re.match(rf"(^|.*\.){k}($|[.\[].*)", path) for k in skip_children_of):
167
167
  return o
168
168
  if isinstance(o, dict):
169
169
  for k, v in dict(o).items():
localstack/utils/run.py CHANGED
@@ -114,7 +114,7 @@ def run(
114
114
  return process
115
115
  except subprocess.CalledProcessError as e:
116
116
  if print_error:
117
- print("ERROR: '%s': exit code %s; output: %s" % (cmd, e.returncode, e.output))
117
+ print(f"ERROR: '{cmd}': exit code {e.returncode}; output: {e.output}")
118
118
  sys.stdout.flush()
119
119
  raise e
120
120
 
@@ -268,7 +268,7 @@ class ShellCommandThread(FuncThread):
268
268
  if self.strip_color:
269
269
  # strip color codes
270
270
  line = re.sub(r"\x1b(\[.*?[@-~]|\].*?(\x07|\x1b\\))", "", line)
271
- return "%s\r\n" % line.strip()
271
+ return f"{line.strip()}\r\n"
272
272
 
273
273
  def filter_line(line):
274
274
  """Return True if this line should be filtered, i.e., not printed"""
@@ -44,7 +44,7 @@ class Server(abc.ABC):
44
44
 
45
45
  @property
46
46
  def url(self):
47
- return "%s://%s:%s" % (self.protocol, self.host, self.port)
47
+ return f"{self.protocol}://{self.host}:{self.port}"
48
48
 
49
49
  def get_error(self) -> Optional[Exception]:
50
50
  """
@@ -42,7 +42,7 @@ def to_bytes(obj: Union[str, bytes], encoding: str = DEFAULT_ENCODING, errors="s
42
42
 
43
43
  def truncate(data: str, max_length: int = 100) -> str:
44
44
  data = str(data or "")
45
- return ("%s..." % data[:max_length]) if len(data) > max_length else data
45
+ return (f"{data[:max_length]}...") if len(data) > max_length else data
46
46
 
47
47
 
48
48
  def is_string(s, include_unicode=True, exclude_binary=False):
@@ -104,11 +104,11 @@ def convert_to_printable_chars(value: Union[list, dict, str]) -> str:
104
104
 
105
105
 
106
106
  def first_char_to_lower(s: str) -> str:
107
- return s and "%s%s" % (s[0].lower(), s[1:])
107
+ return s and f"{s[0].lower()}{s[1:]}"
108
108
 
109
109
 
110
110
  def first_char_to_upper(s: str) -> str:
111
- return s and "%s%s" % (s[0].upper(), s[1:])
111
+ return s and f"{s[0].upper()}{s[1:]}"
112
112
 
113
113
 
114
114
  def str_to_bool(value):
@@ -121,13 +121,13 @@ def str_to_bool(value):
121
121
 
122
122
  def str_insert(string, index, content):
123
123
  """Insert a substring into an existing string at a certain index."""
124
- return "%s%s%s" % (string[:index], content, string[index:])
124
+ return f"{string[:index]}{content}{string[index:]}"
125
125
 
126
126
 
127
127
  def str_remove(string, index, end_index=None):
128
128
  """Remove a substring from an existing string at a certain from-to index range."""
129
129
  end_index = end_index or (index + 1)
130
- return "%s%s" % (string[:index], string[end_index:])
130
+ return f"{string[:index]}{string[end_index:]}"
131
131
 
132
132
 
133
133
  def str_startswith_ignore_case(value: str, prefix: str) -> bool:
@@ -94,7 +94,7 @@ def create_lambda_archive(
94
94
  chmod_r(script_file, 0o777)
95
95
  # copy libs
96
96
  for lib in libs:
97
- paths = [lib, "%s.py" % lib]
97
+ paths = [lib, f"{lib}.py"]
98
98
  try:
99
99
  module = importlib.import_module(lib)
100
100
  paths.append(module.__file__)
@@ -382,7 +382,7 @@ def assert_object(expected_object, all_objects):
382
382
  all_objects = [all_objects]
383
383
  found = find_object(expected_object, all_objects)
384
384
  if not found:
385
- raise Exception("Expected object not found: %s in list %s" % (expected_object, all_objects))
385
+ raise Exception(f"Expected object not found: {expected_object} in list {all_objects}")
386
386
 
387
387
 
388
388
  def find_object(expected_object, object_list):
@@ -522,8 +522,7 @@ def check_expected_lambda_log_events_length(
522
522
  events = [line for line in events if line not in ["\x1b[0m", "\\x1b[0m"]]
523
523
  if len(events) != expected_length:
524
524
  print(
525
- "Invalid # of Lambda %s log events: %s / %s: %s"
526
- % (
525
+ "Invalid # of Lambda {} log events: {} / {}: {}".format(
527
526
  function_name,
528
527
  len(events),
529
528
  expected_length,
localstack/utils/time.py CHANGED
@@ -52,7 +52,7 @@ def parse_timestamp(ts_str: str) -> datetime:
52
52
  return datetime.strptime(ts_str, ts_format)
53
53
  except ValueError:
54
54
  pass
55
- raise Exception("Unable to parse timestamp string with any known formats: %s" % ts_str)
55
+ raise Exception(f"Unable to parse timestamp string with any known formats: {ts_str}")
56
56
 
57
57
 
58
58
  def now(millis: bool = False, tz: Optional[tzinfo] = None) -> int:
@@ -29,7 +29,7 @@ class TraceId:
29
29
  """
30
30
  Convert TraceId object to a string.
31
31
  """
32
- return "%s%s%s%s%s" % (
32
+ return "{}{}{}{}{}".format(
33
33
  TraceId.VERSION,
34
34
  TraceId.DELIMITER,
35
35
  format(self.start_time, "x"),
localstack/version.py CHANGED
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '4.7.1.dev96'
32
- __version_tuple__ = version_tuple = (4, 7, 1, 'dev96')
31
+ __version__ = version = '4.7.1.dev97'
32
+ __version_tuple__ = version_tuple = (4, 7, 1, 'dev97')
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: localstack-core
3
- Version: 4.7.1.dev96
3
+ Version: 4.7.1.dev97
4
4
  Summary: The core library and runtime of LocalStack
5
5
  Author-email: LocalStack Contributors <info@localstack.cloud>
6
6
  License-Expression: Apache-2.0