localstack-core 4.14.1.dev4__py3-none-any.whl → 4.14.1.dev6__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.
@@ -9,7 +9,7 @@ from localstack.aws.api.cloudwatch import MetricAlarm, MetricDataQuery, MetricSt
9
9
  from localstack.aws.connect import connect_to
10
10
  from localstack.runtime.shutdown import SHUTDOWN_HANDLERS
11
11
  from localstack.utils.aws import arns, aws_stack
12
- from localstack.utils.scheduler import Scheduler
12
+ from localstack.utils.scheduler import ScheduledTask, Scheduler
13
13
 
14
14
  if TYPE_CHECKING:
15
15
  from mypy_boto3_cloudwatch import CloudWatchClient
@@ -39,7 +39,7 @@ class AlarmScheduler:
39
39
  """
40
40
  super().__init__()
41
41
  self.scheduler = Scheduler()
42
- self.scheduled_alarms = {}
42
+ self.scheduled_alarms: dict[str, ScheduledTask] = {}
43
43
  self.thread: threading.Thread | None = None
44
44
 
45
45
  def start(self) -> None:
@@ -244,15 +244,16 @@ def collect_metric_data(alarm_details: MetricAlarm, client: "CloudWatchClient")
244
244
  evaluation_periods = alarm_details["EvaluationPeriods"]
245
245
  period = alarm_details["Period"]
246
246
 
247
- # From the docs: "Whenever an alarm evaluates whether to change state, CloudWatch attempts to retrieve a higher number of data
248
- # points than the number specified as Evaluation Periods."
247
+ # From the docs: "Whenever an alarm evaluates whether to change state, CloudWatch attempts to retrieve a
248
+ # higher number of data points than the number specified as Evaluation Periods."
249
249
  # No other indication, try to calculate a reasonable value:
250
250
  magic_number = max(math.floor(evaluation_periods / 3), 2)
251
251
  collected_periods = evaluation_periods + magic_number
252
252
 
253
- now = datetime.utcnow().replace(tzinfo=UTC)
253
+ now = datetime.now(tz=UTC)
254
254
  metric_query = generate_metric_query(alarm_details)
255
255
 
256
+ # Fetching the evaluation range:
256
257
  # get_metric_data needs to be run in a loop, so we also collect empty data points on the right position
257
258
  for i in range(0, collected_periods):
258
259
  start_time = now - timedelta(seconds=period)
@@ -404,6 +405,7 @@ def calculate_alarm_state(alarm_arn: str) -> None:
404
405
  alarm_name,
405
406
  alarm_state,
406
407
  StateValue.OK,
408
+ # TODO: cannot find a snapshot with StateValue.OK and the Threshold crossed value, verify this case
407
409
  THRESHOLD_CROSSED,
408
410
  state_reason_data=state_reason_data,
409
411
  )
@@ -144,3 +144,53 @@ class Tags:
144
144
  """
145
145
 
146
146
  return self._tags.copy()
147
+
148
+
149
+ # Tagging operations for various services return tags in one of two formats:
150
+ #
151
+ # - Tag list: A list of dicts, each dict containing the fields 'Key' and 'Value' and appropriate tag key value pairs.
152
+ # Some services, like CodePipeline, use the fields 'key' and 'value'::
153
+ #
154
+ # [
155
+ # {
156
+ # "Key": "Environment",
157
+ # "Value": "Production",
158
+ # },
159
+ # {
160
+ # "Key": "Owner",
161
+ # "Value": "LocalStack",
162
+ # }
163
+ # ]
164
+ #
165
+ # - Tag map: a direct mapping of tag keys to tag values.::
166
+ #
167
+ # {
168
+ # "Environment": "Production",
169
+ # "Owner": "LocalStack",
170
+ # }
171
+
172
+
173
+ def tag_list_to_map(
174
+ tag_list: list[dict[str, str]], key_field: str = "Key", value_field: str = "Value"
175
+ ) -> dict[str, str]:
176
+ """
177
+ Convert a tag list to a tag map::
178
+
179
+ >> tag_list_to_map([{"Key": "temperature", "Value": "warm"}])
180
+ {"temperature": "warm"}
181
+
182
+ """
183
+ return {tag[key_field]: tag[value_field] for tag in tag_list}
184
+
185
+
186
+ def tag_map_to_list(
187
+ tag_map: dict[str, str], key_field: str = "Key", value_field: str = "Value"
188
+ ) -> list[dict[str, str]]:
189
+ """
190
+ Convert a tag map to a tag list::
191
+
192
+ >> tag_map_to_list({"temperature": "warm"})
193
+ [{"Key": "temperature", "Value": "warm"}]
194
+
195
+ """
196
+ return [{key_field: key, value_field: value} for key, value in tag_map.items()]
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.14.1.dev4'
32
- __version_tuple__ = version_tuple = (4, 14, 1, 'dev4')
31
+ __version__ = version = '4.14.1.dev6'
32
+ __version_tuple__ = version_tuple = (4, 14, 1, 'dev6')
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.14.1.dev4
3
+ Version: 4.14.1.dev6
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
@@ -4,7 +4,7 @@ localstack/deprecations.py,sha256=g0E-_q3apmHlOET2Gg5_biUtN2b4XygnI5aeeaZm6ZY,15
4
4
  localstack/openapi.yaml,sha256=jFUzv-NKkJttxb8HRrmKiNYOmJD-zVfPxG3DDMrRwfg,30865
5
5
  localstack/plugins.py,sha256=BIJC9dlo0WbP7lLKkCiGtd_2q5oeqiHZohvoRTcejXM,2457
6
6
  localstack/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- localstack/version.py,sha256=kHJQWe6DcQah_wqV6Y2z2212D4JnwpZY1AKxtZK68eQ,719
7
+ localstack/version.py,sha256=kR6E-G1eUzv0BV1W6lDvxQziulIsgRU3-tkaSOvu390,719
8
8
  localstack/aws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  localstack/aws/accounts.py,sha256=102zpGowOxo0S6UGMpfjw14QW7WCLVAGsnFK5xFMLoo,3043
10
10
  localstack/aws/app.py,sha256=n9bJCfJRuMz_gLGAH430c3bIQXgUXeWO5NPfcdL2MV8,5145
@@ -337,7 +337,7 @@ localstack/services/cloudformation/v2/provider.py,sha256=1cr_3flqALbY-H40lrVCcIq
337
337
  localstack/services/cloudformation/v2/types.py,sha256=jsfvn2z6weqruaDvv6qtSILtFiOTRl9fIjl0vXvl108,1060
338
338
  localstack/services/cloudformation/v2/utils.py,sha256=U1-YK7BEfA2lRKuUzDUVQ_dXUXybTHciNZA1G3xuZI8,202
339
339
  localstack/services/cloudwatch/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
340
- localstack/services/cloudwatch/alarm_scheduler.py,sha256=6C3LIdgoeiALBSglTILsqxx4jHwlaP81JeS_tVycjiM,16233
340
+ localstack/services/cloudwatch/alarm_scheduler.py,sha256=NXOBIKXAB-zT1Jo_QOSMGFGS5rPK31KVyXKuqq0QJg0,16406
341
341
  localstack/services/cloudwatch/cloudwatch_database_helper.py,sha256=IK_MgxG3xTkpKbBe-Buv_6wUuHEc3MGQOqMAqHoEOzk,17270
342
342
  localstack/services/cloudwatch/models.py,sha256=r-xkCGXjT3YVOBLD0qA7-z85xgPzW-wrk582DzZM1m0,4226
343
343
  localstack/services/cloudwatch/provider.py,sha256=YTtjQLKOLaRVbkUOrkAPCk7Tf8gydncrdQhU3UOHjdI,19308
@@ -1259,7 +1259,7 @@ localstack/utils/serving.py,sha256=wo1jTiqvuNUacuV0aYv2RfDyRd7lxoshrNQ59wjzx8s,5
1259
1259
  localstack/utils/ssl.py,sha256=RGAca4iIYc0tFYcfsev4ea1wOaWE4GuggghcfB8K5Lo,2510
1260
1260
  localstack/utils/strings.py,sha256=CrEoxX_VS51v0xFxhAArnp6_MUFTOR8vR02sWjVn-Ig,7757
1261
1261
  localstack/utils/sync.py,sha256=Q0IscaZX8wdoR4wI7e9VDVBDgIW3YdrY0Av-BJjgQ68,6598
1262
- localstack/utils/tagging.py,sha256=S8uALmOsLwXGVcOynSpe-z4E7gmFZ-X7kzQr5Vgu1NQ,5374
1262
+ localstack/utils/tagging.py,sha256=baqk1sp7zTms49IA_mv1DxCLctSuXXXtGBcRtNW_53k,6787
1263
1263
  localstack/utils/testutil.py,sha256=_YG81sqwl3kFj2kaqbADQUUM61a7TiOGK_1qpxIQnAk,21555
1264
1264
  localstack/utils/threads.py,sha256=6rG43WQnitKkmuAGtIGAzGrRd_sVFQpw1UIRZSSU8JU,5265
1265
1265
  localstack/utils/time.py,sha256=G9GFVkyRNXyqG2SPPARLC-wAcCHXuJLWSqXrnhqNNy8,2260
@@ -1290,7 +1290,6 @@ localstack/utils/aws/message_forwarding.py,sha256=hqxXPV99_DA86bQ6OwkyQ41NKm-bYI
1290
1290
  localstack/utils/aws/queries.py,sha256=cod7Py-UGmffijSpI8J8lpxw5xMN-mT55XD98IhCb_s,1302
1291
1291
  localstack/utils/aws/request_context.py,sha256=9TJZH-soulYu-Kuovg7yY00tIXyQNZipkji6dw0rB-8,3655
1292
1292
  localstack/utils/aws/resources.py,sha256=a5uNFndRShxXeaAwL_V6fuxYxX4ThVqxQ2IRb9FXoGc,7502
1293
- localstack/utils/aws/tags.py,sha256=Q774X6peuwbRO23wCXnic4ZHbl1tD04dV9dCgGvwKAU,1684
1294
1293
  localstack/utils/aws/templating.py,sha256=vHHeAOBPzT4BEQlcG4axl-gIaOJL-o9FBud6l96hKYM,5010
1295
1294
  localstack/utils/catalog/catalog.py,sha256=12RTM5a2ek00ZjUgoZV1_uwIzFZny0RdB7-L98EnfDU,6046
1296
1295
  localstack/utils/catalog/catalog_loader.py,sha256=5w8cLmEZ6ZIueNtS27OOMbeN1x6yWLsQ1DWOb4YC9mM,4765
@@ -1310,10 +1309,10 @@ localstack/utils/server/tcp_proxy.py,sha256=y2NJAmvftTiAYsLU_8qe4W5LGqwUw21i90Pu
1310
1309
  localstack/utils/xray/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1311
1310
  localstack/utils/xray/trace_header.py,sha256=ahXk9eonq7LpeENwlqUEPj3jDOCiVRixhntQuxNor-Q,6209
1312
1311
  localstack/utils/xray/traceid.py,sha256=GKO-R2sMMjlrH2UaLPXlQlZ6flbE7ZKb6IZMtMu_M5U,1110
1313
- localstack_core-4.14.1.dev4.data/scripts/localstack-supervisor,sha256=nm1Il2d6ASyOB6Vo4CRHd90w7TK9FdRl9VPp0NN6hUk,6378
1314
- localstack_core-4.14.1.dev4.dist-info/licenses/LICENSE.txt,sha256=3PC-9Z69UsNARuQ980gNR_JsLx8uvMjdG6C7cc4LBYs,606
1315
- localstack_core-4.14.1.dev4.dist-info/METADATA,sha256=-daGudPmI4gb2aZZF9L1EJfORCQDnsZRYUGqptpA3IQ,5866
1316
- localstack_core-4.14.1.dev4.dist-info/WHEEL,sha256=YCfwYGOYMi5Jhw2fU4yNgwErybb2IX5PEwBKV4ZbdBo,91
1317
- localstack_core-4.14.1.dev4.dist-info/entry_points.txt,sha256=RjwdVn7iE9ehw76CvnylzfeNbWSKO35HLWkGc1Arx6s,20872
1318
- localstack_core-4.14.1.dev4.dist-info/top_level.txt,sha256=3sqmK2lGac8nCy8nwsbS5SpIY_izmtWtgaTFKHYVHbI,11
1319
- localstack_core-4.14.1.dev4.dist-info/RECORD,,
1312
+ localstack_core-4.14.1.dev6.data/scripts/localstack-supervisor,sha256=nm1Il2d6ASyOB6Vo4CRHd90w7TK9FdRl9VPp0NN6hUk,6378
1313
+ localstack_core-4.14.1.dev6.dist-info/licenses/LICENSE.txt,sha256=3PC-9Z69UsNARuQ980gNR_JsLx8uvMjdG6C7cc4LBYs,606
1314
+ localstack_core-4.14.1.dev6.dist-info/METADATA,sha256=ILmCkoI40hbDLnbRh_KAh-zA_XKmZoiMhS5wfZXgqpE,5866
1315
+ localstack_core-4.14.1.dev6.dist-info/WHEEL,sha256=YCfwYGOYMi5Jhw2fU4yNgwErybb2IX5PEwBKV4ZbdBo,91
1316
+ localstack_core-4.14.1.dev6.dist-info/entry_points.txt,sha256=RjwdVn7iE9ehw76CvnylzfeNbWSKO35HLWkGc1Arx6s,20872
1317
+ localstack_core-4.14.1.dev6.dist-info/top_level.txt,sha256=3sqmK2lGac8nCy8nwsbS5SpIY_izmtWtgaTFKHYVHbI,11
1318
+ localstack_core-4.14.1.dev6.dist-info/RECORD,,
@@ -1,44 +0,0 @@
1
- from typing import TypedDict
2
-
3
-
4
- class Tag(TypedDict):
5
- Key: str
6
- Value: str
7
-
8
-
9
- def tag_list_to_dict(tag_list: list[Tag]) -> dict[str, str]:
10
- """
11
- Converts a list of Tag objects into a dictionary, mapping each tag's
12
- "Key" to its "Value". This utility function is useful for transforming
13
- structured tag key-value pairs into a more accessible dictionary format.
14
-
15
- >>>assert tag_list_to_dict([{"Key": "key", "Value": "value"}]) == {"key": "value"}
16
-
17
- :param tag_list: A list of Tag objects where each tag contains a "Key"
18
- and a "Value" pair.
19
- :type tag_list: list[Tag]
20
- :return: A dictionary where each key corresponds to a tag's "Key" and
21
- each value corresponds to a tag's "Value".
22
- :rtype: dict[str, str]
23
- """
24
- return {tag["Key"]: tag["Value"] for tag in tag_list}
25
-
26
-
27
- def tag_dict_to_list(tag_dict: dict[str, str]) -> list[Tag]:
28
- """
29
- Converts a dictionary of tags into a list of Tag objects formatted as dictionaries containing
30
- 'Key' and 'Value'.
31
-
32
- This function takes a dictionary where keys and values represent tag names and their corresponding
33
- values, and transforms it into a list of dictionaries where each dictionary represents a tag with
34
- a 'Key' and a 'Value'.
35
-
36
- >>>assert tag_dict_to_list({"key": "value"}) == [{"Key": "key", "Value": "value"}]
37
-
38
- :param tag_dict: A dictionary where keys represent tag names and values represent tag values.
39
- :type tag_dict: dict[str, str]
40
- :return: A list of dictionaries where each dictionary contains 'Key' and 'Value' representing
41
- a tag.
42
- :rtype: list[Tag]
43
- """
44
- return [{"Key": key, "Value": value} for key, value in tag_dict.items()]