aws-annoying 0.5.0__py3-none-any.whl → 0.7.0__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.
Files changed (33) hide show
  1. aws_annoying/cli/app.py +81 -0
  2. aws_annoying/cli/ecs/__init__.py +3 -0
  3. aws_annoying/cli/ecs/_app.py +9 -0
  4. aws_annoying/cli/{ecs_task_definition_lifecycle.py → ecs/task_definition_lifecycle.py} +18 -13
  5. aws_annoying/cli/ecs/wait_for_deployment.py +158 -0
  6. aws_annoying/cli/load_variables.py +20 -25
  7. aws_annoying/cli/logging_handler.py +52 -0
  8. aws_annoying/cli/main.py +1 -1
  9. aws_annoying/cli/mfa/configure.py +21 -12
  10. aws_annoying/cli/session_manager/_common.py +1 -32
  11. aws_annoying/cli/session_manager/install.py +8 -5
  12. aws_annoying/cli/session_manager/port_forward.py +22 -12
  13. aws_annoying/cli/session_manager/start.py +13 -5
  14. aws_annoying/cli/session_manager/stop.py +9 -7
  15. aws_annoying/ecs/__init__.py +25 -0
  16. aws_annoying/ecs/check.py +39 -0
  17. aws_annoying/ecs/common.py +8 -0
  18. aws_annoying/ecs/errors.py +14 -0
  19. aws_annoying/ecs/wait_for.py +190 -0
  20. aws_annoying/{mfa.py → mfa_config.py} +7 -2
  21. aws_annoying/session_manager/session_manager.py +2 -4
  22. aws_annoying/session_manager/shortcuts.py +10 -6
  23. aws_annoying/utils/downloader.py +1 -8
  24. aws_annoying/utils/ec2.py +33 -0
  25. aws_annoying/utils/platform.py +11 -0
  26. aws_annoying/utils/timeout.py +85 -0
  27. aws_annoying/{variables.py → variable_loader.py} +11 -16
  28. {aws_annoying-0.5.0.dist-info → aws_annoying-0.7.0.dist-info}/METADATA +48 -3
  29. aws_annoying-0.7.0.dist-info/RECORD +42 -0
  30. aws_annoying-0.5.0.dist-info/RECORD +0 -31
  31. {aws_annoying-0.5.0.dist-info → aws_annoying-0.7.0.dist-info}/WHEEL +0 -0
  32. {aws_annoying-0.5.0.dist-info → aws_annoying-0.7.0.dist-info}/entry_points.txt +0 -0
  33. {aws_annoying-0.5.0.dist-info → aws_annoying-0.7.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import os
4
+ import platform
4
5
  from pathlib import Path
5
6
 
6
7
 
@@ -25,3 +26,13 @@ def os_release() -> dict[str, str]:
25
26
  key.strip('"'): value.strip('"')
26
27
  for key, value in (line.split("=", 1) for line in content.splitlines() if "=" in line)
27
28
  }
29
+
30
+
31
+ def is_macos() -> bool:
32
+ """Check if the current OS is macOS."""
33
+ return platform.system() == "Darwin"
34
+
35
+
36
+ def is_windows() -> bool:
37
+ """Check if the current OS is Windows."""
38
+ return platform.system() == "Windows"
@@ -0,0 +1,85 @@
1
+ from __future__ import annotations
2
+
3
+ import signal
4
+ from functools import wraps
5
+ from typing import TYPE_CHECKING, Callable, TypeVar, cast
6
+
7
+ from aws_annoying.utils.platform import is_windows
8
+
9
+ if TYPE_CHECKING:
10
+ from types import FrameType
11
+ from typing import Any
12
+
13
+
14
+ class OperationTimeoutError(Exception):
15
+ """Operation timed out."""
16
+
17
+
18
+ _F = TypeVar("_F", bound=Callable)
19
+
20
+
21
+ class Timeout:
22
+ """Timeout handler utilizing signals.
23
+
24
+ This utility relies on Unix signals (`signal.SIGALRM`). The behavior will be dummied
25
+ to do nothing on Windows OS.
26
+ """
27
+
28
+ def __init__(self, seconds: int | None) -> None:
29
+ """Initialize timeout handler.
30
+
31
+ Args:
32
+ seconds: The timeout in seconds. `None` means no timeout,
33
+ allowing the function to run normally.
34
+
35
+ """
36
+ self.timeout_seconds = seconds
37
+
38
+ self._signal_handler_registered = False
39
+
40
+ def _set_signal_handler(self) -> None:
41
+ if is_windows() or self.timeout_seconds is None:
42
+ return
43
+
44
+ signal.signal(signal.SIGALRM, self._handler)
45
+ signal.alarm(self.timeout_seconds)
46
+ self._signal_handler_registered = True
47
+
48
+ def _handler(self, signum: int, frame: FrameType | None) -> Any: # noqa: ARG002
49
+ msg = "Timeout reached"
50
+ raise OperationTimeoutError(msg)
51
+
52
+ def _reset_signal_handler(self) -> None:
53
+ if is_windows() or not self._signal_handler_registered:
54
+ return
55
+
56
+ signal.signal(signal.SIGALRM, signal.SIG_IGN)
57
+ signal.alarm(0)
58
+ self._signal_handler_registered = False
59
+
60
+ def __call__(self, func: _F) -> _F:
61
+ """Decorator to set a timeout for a function.
62
+
63
+ Please note, using this decorator in nested functions may not work properly as
64
+ the signal handler for outer functions may not be resumed correctly.
65
+
66
+ Raises:
67
+ OperationTimeoutError: When timeout is reached.
68
+ """
69
+
70
+ @wraps(func)
71
+ def wrapper(*args: Any, **kwargs: Any) -> Any:
72
+ self._set_signal_handler()
73
+ try:
74
+ return func(*args, **kwargs)
75
+ finally:
76
+ self._reset_signal_handler()
77
+
78
+ return cast("_F", wrapper)
79
+
80
+ def __enter__(self) -> None:
81
+ self._set_signal_handler()
82
+
83
+ def __exit__(self, *args: object) -> Any:
84
+ self._reset_signal_handler()
85
+ return False # Re-raise
@@ -2,17 +2,17 @@
2
2
  from __future__ import annotations
3
3
 
4
4
  import json
5
+ import logging
5
6
  from typing import Any, TypedDict
6
7
 
7
8
  import boto3
8
9
 
10
+ logger = logging.getLogger(__name__)
11
+
9
12
  # Type aliases for readability
10
13
  _ARN = str
11
14
  _Variables = dict[str, Any]
12
15
 
13
- # TODO(lasuillard): Need some refactoring (with #2, #3)
14
- # TODO(lasuillard): Put some logging
15
-
16
16
 
17
17
  class _LoadStatsDict(TypedDict):
18
18
  secrets: int
@@ -20,14 +20,13 @@ class _LoadStatsDict(TypedDict):
20
20
 
21
21
 
22
22
  class VariableLoader: # noqa: D101
23
- def __init__(self, *, dry_run: bool) -> None:
24
- """Initialize the VariableLoader.
23
+ def __init__(self, *, session: boto3.session.Session | None = None) -> None:
24
+ """Initialize variable loader.
25
25
 
26
26
  Args:
27
- dry_run: Whether to run in dry-run mode.
28
- console: Rich console instance.
27
+ session: Boto3 session to use for AWS operations.
29
28
  """
30
- self.dry_run = dry_run
29
+ self.session = session or boto3.session.Session()
31
30
 
32
31
  # TODO(lasuillard): Currently not using pagination (do we need more than 10-20 secrets or parameters each?)
33
32
  # ; consider adding it if needed
@@ -54,12 +53,8 @@ class VariableLoader: # noqa: D101
54
53
  # Retrieve variables from AWS resources
55
54
  secrets: dict[str, _Variables]
56
55
  parameters: dict[str, _Variables]
57
- if self.dry_run:
58
- secrets = {idx: {} for idx, _ in secrets_map.items()}
59
- parameters = {idx: {} for idx, _ in parameters_map.items()}
60
- else:
61
- secrets = self._retrieve_secrets(secrets_map)
62
- parameters = self._retrieve_parameters(parameters_map)
56
+ secrets = self._retrieve_secrets(secrets_map)
57
+ parameters = self._retrieve_parameters(parameters_map)
63
58
 
64
59
  load_stats: _LoadStatsDict = {
65
60
  "secrets": len(secrets),
@@ -79,7 +74,7 @@ class VariableLoader: # noqa: D101
79
74
  if not secrets_map:
80
75
  return {}
81
76
 
82
- secretsmanager = boto3.client("secretsmanager")
77
+ secretsmanager = self.session.client("secretsmanager")
83
78
 
84
79
  # Retrieve the secrets
85
80
  arns = list(secrets_map.values())
@@ -108,7 +103,7 @@ class VariableLoader: # noqa: D101
108
103
  if not parameters_map:
109
104
  return {}
110
105
 
111
- ssm = boto3.client("ssm")
106
+ ssm = self.session.client("ssm")
112
107
 
113
108
  # Retrieve the parameters
114
109
  parameter_names = list(parameters_map.values())
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aws-annoying
3
- Version: 0.5.0
3
+ Version: 0.7.0
4
4
  Summary: Utils to handle some annoying AWS tasks.
5
5
  Project-URL: Homepage, https://github.com/lasuillard/aws-annoying
6
6
  Project-URL: Repository, https://github.com/lasuillard/aws-annoying.git
@@ -16,19 +16,21 @@ Requires-Dist: tqdm<5,>=4
16
16
  Requires-Dist: typer<1,>=0
17
17
  Provides-Extra: dev
18
18
  Requires-Dist: boto3-stubs[ec2,ecs,secretsmanager,ssm,sts]>=1.37.1; extra == 'dev'
19
- Requires-Dist: mypy~=1.15.0; extra == 'dev'
19
+ Requires-Dist: mypy<1.17,>=1.15; extra == 'dev'
20
20
  Requires-Dist: ruff<0.12.0,>=0.9.9; extra == 'dev'
21
21
  Requires-Dist: types-requests>=2.31.0.6; extra == 'dev'
22
22
  Provides-Extra: test
23
23
  Requires-Dist: coverage<7.9,>=7.6; extra == 'test'
24
24
  Requires-Dist: moto[ecs,secretsmanager,server,ssm]~=5.1.1; extra == 'test'
25
- Requires-Dist: pytest-cov~=6.0.0; extra == 'test'
25
+ Requires-Dist: pytest-cov<6.2,>=6.0; extra == 'test'
26
26
  Requires-Dist: pytest-env~=1.1.1; extra == 'test'
27
27
  Requires-Dist: pytest-snapshot>=0.9.0; extra == 'test'
28
28
  Requires-Dist: pytest-sugar~=1.0.0; extra == 'test'
29
29
  Requires-Dist: pytest-xdist>=3.6.1; extra == 'test'
30
30
  Requires-Dist: pytest~=8.3.2; extra == 'test'
31
31
  Requires-Dist: testcontainers[localstack]>=4.9.2; extra == 'test'
32
+ Requires-Dist: toml>=0.10.2; extra == 'test'
33
+ Requires-Dist: types-toml>=0.10.8.20240310; extra == 'test'
32
34
  Description-Content-Type: text/markdown
33
35
 
34
36
  # aws-annoying
@@ -39,3 +41,46 @@ Description-Content-Type: text/markdown
39
41
  ![PyPI - Version](https://img.shields.io/pypi/v/aws-annoying)
40
42
 
41
43
  Utils to handle some annoying AWS tasks.
44
+
45
+ ## ❓ About
46
+
47
+ This project aims to provide a set of utilities and examples to help with some annoying tasks when working with AWS.
48
+
49
+ Major directories of the project:
50
+
51
+ - **aws_annoying** Python package containing CLI and utility functions.
52
+ - **console** Utilities to help working with AWS Console.
53
+ - **examples** Examples of how to use the package.
54
+
55
+ ## 🚀 Installation
56
+
57
+ It is recommended to use [pipx](https://pipx.pypa.io/stable/) to install `aws-annoying`:
58
+
59
+ ```bash
60
+ $ pipx install aws-annoying
61
+ $ aws-annoying --help
62
+
63
+ Usage: aws-annoying [OPTIONS] COMMAND [ARGS]...
64
+
65
+ ...
66
+ ```
67
+
68
+ Available commands:
69
+
70
+ - **ecs** ECS utilities.
71
+ - **task-definition-lifecycle** Help to manage ECS task definitions lifecycle.
72
+ - **wait-for-deployment** Wait for ECS deployment to complete.
73
+ - **load-variables** Wrapper command to run command with variables from AWS resources injected as environment variables.
74
+ - **mfa** Commands to manage MFA authentication.
75
+ - **configure** Configure AWS profile for MFA.
76
+ - **session-manager** AWS Session Manager CLI utilities.
77
+ - **install** Install AWS Session Manager plugin.
78
+ - **port-forward** Start a port forwarding session using AWS Session Manager.
79
+ - **start** Start new session.
80
+ - **stop** Stop running session for PID file.
81
+
82
+ Please refer to the CLI help for more information about the available commands and options.
83
+
84
+ ## 💖 Contributing
85
+
86
+ Any feedback, suggestions or contributions are welcome! Feel free to open an issue or a pull request.
@@ -0,0 +1,42 @@
1
+ aws_annoying/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ aws_annoying/mfa_config.py,sha256=z0GpRhLHEWaaXbECV4Ei4oNM1WCFoEZAxCIPbpY4Ymc,2200
3
+ aws_annoying/variable_loader.py,sha256=N9qPPHG6mzSIIHrWJnJ_FV5kKZxssOaTHoAQEwiDE3s,4569
4
+ aws_annoying/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ aws_annoying/cli/app.py,sha256=6opsAfIFGPnUSK68s7sEnFzLhipnevfP2cDJ0yj7Lh0,2366
6
+ aws_annoying/cli/load_variables.py,sha256=n5CIci_uAoGaOZ4EKIKEEfcyMq81Hjy9AFOXq1-Hbh0,4896
7
+ aws_annoying/cli/logging_handler.py,sha256=JPsZePV3YH9e1nLv0Q3fqSeXSEfZ5cGJo6eLK2F4oxE,1426
8
+ aws_annoying/cli/main.py,sha256=bU4Gxic5_3qrrd8l9eN709-D4o_OHgrdH91FS9Xs8zI,477
9
+ aws_annoying/cli/ecs/__init__.py,sha256=IxfaMXcGU6WTHE_RXj-aitXtSg25j5m3HGTG9O02GjI,125
10
+ aws_annoying/cli/ecs/_app.py,sha256=izD0VL55i7oG-2CtWCV21bSoAeE-DZbxyJ5pi6VXhjU,200
11
+ aws_annoying/cli/ecs/task_definition_lifecycle.py,sha256=W7zr8zEPjjHgss9Tnb3QMcJ_45Yb9SJ5D1B315vb9kc,2803
12
+ aws_annoying/cli/ecs/wait_for_deployment.py,sha256=yBl-KMOya8ZSgpZLcEB0UqtsZfK5ezKPJWNaOdMRRcY,5234
13
+ aws_annoying/cli/mfa/__init__.py,sha256=rbEGhw5lOQZV_XAc3nSbo56JVhsSPpeOgEtiAy9qzEA,50
14
+ aws_annoying/cli/mfa/_app.py,sha256=Ub7gxb6kGF3Ve1ucQSOjHmc4jAu8mxgegcXsIbOzLLQ,189
15
+ aws_annoying/cli/mfa/configure.py,sha256=s2SCz7gzvIE9mJM7w95JPwoGhuQrgkFhjUd6qjD169k,3957
16
+ aws_annoying/cli/session_manager/__init__.py,sha256=FkT6jT6OXduOURN61d-U6hgd-XluQbvuVtKXXiXgSEk,105
17
+ aws_annoying/cli/session_manager/_app.py,sha256=OVOHW0iyKzunvaqLhjoseHw1-WxJ1gGb7QmiyAEezyY,221
18
+ aws_annoying/cli/session_manager/_common.py,sha256=Uj-MF7z8Qntd24Z03xxE-jSKcgrsd8xl41E6db4qCtY,711
19
+ aws_annoying/cli/session_manager/install.py,sha256=VIk6313jUf6THwvs06AOUQwhTjzCGCcvDXMxyz0BcgE,1477
20
+ aws_annoying/cli/session_manager/port_forward.py,sha256=upsUsd7MkUfaAP3o0ZK6N-SkOBnr1ogwqYozG4TDTzY,4331
21
+ aws_annoying/cli/session_manager/start.py,sha256=1Q-WFvbQkMgVntwIrM2HfpUKmVL38aFrjJjG3aA0fzU,1447
22
+ aws_annoying/cli/session_manager/stop.py,sha256=QjjOmmhZr_0IInhOyHvSlodk7Nx4qu9EtrRw4kl8Hks,1535
23
+ aws_annoying/ecs/__init__.py,sha256=G9vVNkbDg-fY3G0Qc7yOGZOnsVp4VtiwzzEgjr6S5Kw,666
24
+ aws_annoying/ecs/check.py,sha256=mxkW8MWCJYng60VKwq3Ws9PEvI1u0aVPdbs4p6SY2j4,1233
25
+ aws_annoying/ecs/common.py,sha256=TvP27SEvdIBnA92Oude-oDCy1SuaYNdtpokkbpZmdzo,139
26
+ aws_annoying/ecs/errors.py,sha256=n9j_h1MDUV6IVabKgwbCVAiPZQNJDJ5rVRHA82Je5QQ,429
27
+ aws_annoying/ecs/wait_for.py,sha256=Oj1u1uPp074-Pf-cvVNHxs-S6RLk8lh5EGsVFqi1iH0,6123
28
+ aws_annoying/session_manager/__init__.py,sha256=IENviL3ux2LF7o9xFGYEiqaGw03hxnyNX2btbB1xyEU,318
29
+ aws_annoying/session_manager/errors.py,sha256=YioKlRtZ-GUP0F_ts_ebw7-HYkxe8mTes6HK821Kuiw,353
30
+ aws_annoying/session_manager/session_manager.py,sha256=pUsyJ_w9UzdIfHA2Z8kU6UcZxOqypFXH1rl6pDytdqo,12046
31
+ aws_annoying/session_manager/shortcuts.py,sha256=Yn4wCl43lfttrZ7GbzfGua2jZHe5Fe6ClEy4ikg-Q_s,2143
32
+ aws_annoying/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
+ aws_annoying/utils/debugger.py,sha256=UFllDCGI2gPtwo1XS5vqw0qyR6bYr7XknmBwSxalKIc,754
34
+ aws_annoying/utils/downloader.py,sha256=bAh8Hu55L3F8Fyd1s4NBsyB_L0U-lk7SfKsS00Rp5fA,1660
35
+ aws_annoying/utils/ec2.py,sha256=VsOrnFQDSNplWQ_s-uT11IfiD2mi-74uLbSVoaeXynI,1055
36
+ aws_annoying/utils/platform.py,sha256=TBIzCzYiFj36HmndZedegvFlxPSNtBQyAxzuwelvxNg,985
37
+ aws_annoying/utils/timeout.py,sha256=9eCSqhkEp7f7wBoLzkyqfyUKAgY9irwL6LIWBvIvmFI,2394
38
+ aws_annoying-0.7.0.dist-info/METADATA,sha256=eUE6FIYZGklV_MNFNBDH9CSLQXLXZN5KlNYYkF4cifw,3507
39
+ aws_annoying-0.7.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
40
+ aws_annoying-0.7.0.dist-info/entry_points.txt,sha256=DcKE5V0WvVJ8wUOHxyUz1yLAJOuuJUgRPlMcQ4O7jEs,66
41
+ aws_annoying-0.7.0.dist-info/licenses/LICENSE,sha256=Q5GkvYijQ2KTQ-QWhv43ilzCno4ZrzrEuATEQZd9rYo,1067
42
+ aws_annoying-0.7.0.dist-info/RECORD,,
@@ -1,31 +0,0 @@
1
- aws_annoying/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- aws_annoying/mfa.py,sha256=m6-V1bWeUWsAmRddl-lv13mPCMnftoPzJoNnZ0kiaWQ,2007
3
- aws_annoying/variables.py,sha256=a9cMS9JU-XA2h1tztO7ofixoDEpqtS_eVEiWrQ75mTo,4761
4
- aws_annoying/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- aws_annoying/cli/app.py,sha256=sp50uVoAl4D6Wk3DFpzKZzSsxmSxNYejFxm62b_Kxps,201
6
- aws_annoying/cli/ecs_task_definition_lifecycle.py,sha256=O36Bf5LBnVJNyYmdlUxhtsIHNoxky1t5YacAXiL9UEI,2803
7
- aws_annoying/cli/load_variables.py,sha256=eWNByUEc1ijF8uCe_egdAnjWxfMNCZeVr0vtTtQLe3Y,5086
8
- aws_annoying/cli/main.py,sha256=TSzPeMkgIgKFf3bom_vDkFYK0bHF1r5K9ADreZUV3k4,503
9
- aws_annoying/cli/mfa/__init__.py,sha256=rbEGhw5lOQZV_XAc3nSbo56JVhsSPpeOgEtiAy9qzEA,50
10
- aws_annoying/cli/mfa/_app.py,sha256=Ub7gxb6kGF3Ve1ucQSOjHmc4jAu8mxgegcXsIbOzLLQ,189
11
- aws_annoying/cli/mfa/configure.py,sha256=vsoHfTVFF2dPgiYsp2L-EkMwtAA0_-tVwFd6Wv6DscU,3746
12
- aws_annoying/cli/session_manager/__init__.py,sha256=FkT6jT6OXduOURN61d-U6hgd-XluQbvuVtKXXiXgSEk,105
13
- aws_annoying/cli/session_manager/_app.py,sha256=OVOHW0iyKzunvaqLhjoseHw1-WxJ1gGb7QmiyAEezyY,221
14
- aws_annoying/cli/session_manager/_common.py,sha256=u23F4mJOHWHphLYL1gOAh8J3a_Odyk4VVvI175KWmzg,1616
15
- aws_annoying/cli/session_manager/install.py,sha256=zcQi91xVFKhbSOD4VBc6YG9-fDnhymVyK63PlITdxug,1445
16
- aws_annoying/cli/session_manager/port_forward.py,sha256=J8_CIrTsbcOYRYOdHkdz81dkaNWxI_l70E8gyJ-Ukh8,4192
17
- aws_annoying/cli/session_manager/start.py,sha256=pPS0jKuURGTX-WTix3owqqisX-bmCydqfyqC0kFGnt8,1358
18
- aws_annoying/cli/session_manager/stop.py,sha256=ttU6nlbVgBkZDtY-DwUyCstv5TFtat5TljkyuY8QICU,1482
19
- aws_annoying/session_manager/__init__.py,sha256=IENviL3ux2LF7o9xFGYEiqaGw03hxnyNX2btbB1xyEU,318
20
- aws_annoying/session_manager/errors.py,sha256=YioKlRtZ-GUP0F_ts_ebw7-HYkxe8mTes6HK821Kuiw,353
21
- aws_annoying/session_manager/session_manager.py,sha256=myZxY_WE4akdlTsH1mOvf0Ublwg-hf1vEkEcmdZyYSU,12147
22
- aws_annoying/session_manager/shortcuts.py,sha256=uFRPGia_5gqfBDxwOjmLg7UFzhvkSFUqopWuzN5_kbA,1973
23
- aws_annoying/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
- aws_annoying/utils/debugger.py,sha256=UFllDCGI2gPtwo1XS5vqw0qyR6bYr7XknmBwSxalKIc,754
25
- aws_annoying/utils/downloader.py,sha256=aB5RzT-LpbFX24-2HXlAkdgVowc4TR9FWT_K8WwZ1BE,1923
26
- aws_annoying/utils/platform.py,sha256=h3DUWmTMM-_4TfTWNqY0uNqyVsBjAuMm2DEbG-daxe8,742
27
- aws_annoying-0.5.0.dist-info/METADATA,sha256=kHaGAHqfkZ8Ip4NzcLbE7Bh01oA1CvoTsUa3Ljx1ctU,1916
28
- aws_annoying-0.5.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
29
- aws_annoying-0.5.0.dist-info/entry_points.txt,sha256=DcKE5V0WvVJ8wUOHxyUz1yLAJOuuJUgRPlMcQ4O7jEs,66
30
- aws_annoying-0.5.0.dist-info/licenses/LICENSE,sha256=Q5GkvYijQ2KTQ-QWhv43ilzCno4ZrzrEuATEQZd9rYo,1067
31
- aws_annoying-0.5.0.dist-info/RECORD,,