simple_aws_lambda 0.3.1__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.
- simple_aws_lambda/__init__.py +1 -0
- simple_aws_lambda/api.py +22 -0
- simple_aws_lambda/client.py +140 -0
- simple_aws_lambda/model.py +488 -0
- simple_aws_lambda/paths.py +60 -0
- simple_aws_lambda/recipe.py +320 -0
- simple_aws_lambda/vendor/__init__.py +2 -0
- simple_aws_lambda/vendor/pytest_cov_helper.py +148 -0
- simple_aws_lambda-0.3.1.dist-info/METADATA +134 -0
- simple_aws_lambda-0.3.1.dist-info/RECORD +14 -0
- simple_aws_lambda-0.3.1.dist-info/WHEEL +5 -0
- simple_aws_lambda-0.3.1.dist-info/licenses/AUTHORS.rst +15 -0
- simple_aws_lambda-0.3.1.dist-info/licenses/LICENSE.txt +21 -0
- simple_aws_lambda-0.3.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
simple_aws_lambda/api.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Public API. Users import from here::
|
|
5
|
+
|
|
6
|
+
from simple_aws_lambda.api import list_layers
|
|
7
|
+
import simple_aws_lambda.api as simple_aws_lambda
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from .model import LatestMatchingLayerVersion
|
|
11
|
+
from .model import Layer
|
|
12
|
+
from .model import LayerIterproxy
|
|
13
|
+
from .model import LayerContent
|
|
14
|
+
from .model import LayerVersion
|
|
15
|
+
from .model import LayerVersionIterproxy
|
|
16
|
+
from .client import list_layers
|
|
17
|
+
from .client import list_layer_versions
|
|
18
|
+
from .client import get_layer_version
|
|
19
|
+
from .recipe import get_latest_layer_version
|
|
20
|
+
from .recipe import cleanup_old_layer_versions
|
|
21
|
+
from .recipe import grant_aws_account_or_aws_organization_lambda_layer_version_access
|
|
22
|
+
from .recipe import revoke_aws_account_or_aws_organization_lambda_layer_version_access
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Improve the original lambda boto3 API.
|
|
5
|
+
|
|
6
|
+
Ref:
|
|
7
|
+
|
|
8
|
+
- https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/lambda.html
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import typing as T
|
|
14
|
+
|
|
15
|
+
import botocore.exceptions
|
|
16
|
+
from func_args.api import OPT
|
|
17
|
+
from func_args.api import remove_optional
|
|
18
|
+
|
|
19
|
+
from .model import Layer
|
|
20
|
+
from .model import LayerVersion
|
|
21
|
+
from .model import LayerIterproxy
|
|
22
|
+
from .model import LayerVersionIterproxy
|
|
23
|
+
|
|
24
|
+
if T.TYPE_CHECKING: # pragma: no cover
|
|
25
|
+
from mypy_boto3_lambda.client import LambdaClient
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def list_layers(
|
|
29
|
+
lambda_client: LambdaClient,
|
|
30
|
+
compatible_runtime: str = OPT,
|
|
31
|
+
compatible_architecture: str = OPT,
|
|
32
|
+
max_items: int = 9999,
|
|
33
|
+
page_size: int = 50,
|
|
34
|
+
) -> LayerIterproxy:
|
|
35
|
+
"""
|
|
36
|
+
List available AWS Lambda layers in the account.
|
|
37
|
+
|
|
38
|
+
Ref:
|
|
39
|
+
|
|
40
|
+
- `list_layers <https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/lambda/client/list_layers.html>`_
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
def func():
|
|
44
|
+
paginator = lambda_client.get_paginator("list_layers")
|
|
45
|
+
response_iterator = paginator.paginate(
|
|
46
|
+
**remove_optional(
|
|
47
|
+
CompatibleRuntime=compatible_runtime,
|
|
48
|
+
CompatibleArchitecture=compatible_architecture,
|
|
49
|
+
PaginationConfig={
|
|
50
|
+
"MaxItems": max_items,
|
|
51
|
+
"PageSize": page_size,
|
|
52
|
+
},
|
|
53
|
+
)
|
|
54
|
+
)
|
|
55
|
+
for response in response_iterator:
|
|
56
|
+
for _data in response.get("Layers", []):
|
|
57
|
+
yield Layer(_data=_data)
|
|
58
|
+
|
|
59
|
+
return LayerIterproxy(func())
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def list_layer_versions(
|
|
63
|
+
lambda_client: LambdaClient,
|
|
64
|
+
layer_name: str,
|
|
65
|
+
compatible_runtime: str = OPT,
|
|
66
|
+
compatible_architecture: str = OPT,
|
|
67
|
+
max_items: int = 9999,
|
|
68
|
+
page_size: int = 50,
|
|
69
|
+
_sort_descending: bool = False,
|
|
70
|
+
) -> LayerVersionIterproxy:
|
|
71
|
+
"""
|
|
72
|
+
List all versions of Lambda layers in the account.
|
|
73
|
+
|
|
74
|
+
:param _sort_descending: if True, load all layer versions in to memory and
|
|
75
|
+
then sort them in memory in descending order by version number. This is
|
|
76
|
+
the default behavior of official AWS API. However, the test tool moto does not
|
|
77
|
+
implement it correctly (it returns in ascending order). So this parameter
|
|
78
|
+
is a workaround for moto only. You don't need to set this parameter
|
|
79
|
+
when you run against real AWS API.
|
|
80
|
+
|
|
81
|
+
.. note::
|
|
82
|
+
|
|
83
|
+
this API always returns the latest version first.
|
|
84
|
+
|
|
85
|
+
Ref:
|
|
86
|
+
|
|
87
|
+
- `list_layer_versions <https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/lambda/client/list_layer_versions.html>`_
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
def func():
|
|
91
|
+
paginator = lambda_client.get_paginator("list_layer_versions")
|
|
92
|
+
response_iterator = paginator.paginate(
|
|
93
|
+
**remove_optional(
|
|
94
|
+
LayerName=layer_name,
|
|
95
|
+
CompatibleRuntime=compatible_runtime,
|
|
96
|
+
CompatibleArchitecture=compatible_architecture,
|
|
97
|
+
PaginationConfig={
|
|
98
|
+
"MaxItems": max_items,
|
|
99
|
+
"PageSize": page_size,
|
|
100
|
+
},
|
|
101
|
+
)
|
|
102
|
+
)
|
|
103
|
+
for response in response_iterator:
|
|
104
|
+
for _data in response.get("LayerVersions", []):
|
|
105
|
+
yield LayerVersion(_data=_data)
|
|
106
|
+
|
|
107
|
+
if _sort_descending:
|
|
108
|
+
return LayerVersionIterproxy(
|
|
109
|
+
sorted(
|
|
110
|
+
func(),
|
|
111
|
+
key=lambda v: v.version,
|
|
112
|
+
reverse=True,
|
|
113
|
+
)
|
|
114
|
+
)
|
|
115
|
+
else:
|
|
116
|
+
return LayerVersionIterproxy(func())
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def get_layer_version(
|
|
120
|
+
lambda_client: LambdaClient,
|
|
121
|
+
layer_name: str,
|
|
122
|
+
version_number: int,
|
|
123
|
+
) -> LayerVersion | None:
|
|
124
|
+
"""
|
|
125
|
+
Retrieve details for a specific Lambda layer version.
|
|
126
|
+
|
|
127
|
+
Ref:
|
|
128
|
+
|
|
129
|
+
- `get_layer_version <https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/lambda/client/get_layer_version.html>`_
|
|
130
|
+
"""
|
|
131
|
+
try:
|
|
132
|
+
response = lambda_client.get_layer_version(
|
|
133
|
+
LayerName=layer_name,
|
|
134
|
+
VersionNumber=version_number,
|
|
135
|
+
)
|
|
136
|
+
return LayerVersion(_data=response)
|
|
137
|
+
except botocore.exceptions.ClientError as e:
|
|
138
|
+
if e.response["Error"]["Code"] == "ResourceNotFoundException":
|
|
139
|
+
return None
|
|
140
|
+
raise # pragma: no cover
|
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Base model implementation for AWS Lambda objects.
|
|
5
|
+
|
|
6
|
+
This module provides the foundational data models for the AWS Lambda library,
|
|
7
|
+
implementing common patterns for representing and interacting with AWS Lambda resources.
|
|
8
|
+
The models follow three key design patterns:
|
|
9
|
+
|
|
10
|
+
1. **Raw Data Storage Pattern**:
|
|
11
|
+
|
|
12
|
+
All models store the original API response data in a `_data` attribute, treating the
|
|
13
|
+
API response schema as potentially unstable. Properties provide a stable interface
|
|
14
|
+
for accessing the underlying data, making the code more resilient to API changes.
|
|
15
|
+
|
|
16
|
+
2. **Property-Based Access Pattern**:
|
|
17
|
+
|
|
18
|
+
All attributes are exposed through properties rather than direct instance attributes.
|
|
19
|
+
This approach allows for lazy loading, data validation, and type conversion while
|
|
20
|
+
maintaining a clean public interface.
|
|
21
|
+
|
|
22
|
+
3. **Core Data Extraction Pattern**:
|
|
23
|
+
|
|
24
|
+
Each model implements a `core_data` property that returns a standardized, minimal
|
|
25
|
+
representation of the object. This provides a consistent way to access essential
|
|
26
|
+
information across different model types.
|
|
27
|
+
|
|
28
|
+
These models are designed to be instantiated by the API client methods, not directly
|
|
29
|
+
by users of the library. They provide a Pythonic interface to the JSON data returned
|
|
30
|
+
by the native boto3 AWS Lambda API.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
from __future__ import annotations
|
|
34
|
+
|
|
35
|
+
import typing as T
|
|
36
|
+
import dataclasses
|
|
37
|
+
from datetime import datetime
|
|
38
|
+
from datetime import timezone
|
|
39
|
+
|
|
40
|
+
from func_args.api import T_KWARGS
|
|
41
|
+
from func_args.api import REQ
|
|
42
|
+
from iterproxy import IterProxy
|
|
43
|
+
|
|
44
|
+
if T.TYPE_CHECKING: # pragma: no cover
|
|
45
|
+
from mypy_boto3_lambda.type_defs import LayersListItemTypeDef
|
|
46
|
+
from mypy_boto3_lambda.type_defs import LayerVersionsListItemTypeDef
|
|
47
|
+
from mypy_boto3_lambda.type_defs import GetLayerVersionResponseTypeDef
|
|
48
|
+
from mypy_boto3_lambda.type_defs import LayerVersionContentOutputTypeDef
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@dataclasses.dataclass(frozen=True)
|
|
52
|
+
class Base:
|
|
53
|
+
_data: dict[str, T.Any] = dataclasses.field(default=REQ)
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def core_data(self) -> T_KWARGS:
|
|
57
|
+
raise NotImplementedError
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@dataclasses.dataclass(frozen=True)
|
|
61
|
+
class LatestMatchingLayerVersion(Base):
|
|
62
|
+
"""
|
|
63
|
+
Represents the latest matching version of a Lambda layer.
|
|
64
|
+
|
|
65
|
+
Ref:
|
|
66
|
+
|
|
67
|
+
- `list_layers <https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/lambda/client/list_layers.html>`_
|
|
68
|
+
|
|
69
|
+
:param _data: Raw data structure as returned by AWS SDK:
|
|
70
|
+
|
|
71
|
+
.. code-block:: python
|
|
72
|
+
|
|
73
|
+
{
|
|
74
|
+
'LayerVersionArn': 'string',
|
|
75
|
+
'Version': 123,
|
|
76
|
+
'Description': 'string',
|
|
77
|
+
...
|
|
78
|
+
}
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
_data: LayerVersionsListItemTypeDef = dataclasses.field(default=REQ)
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def layer_version_arn(self) -> str | None:
|
|
85
|
+
"""The ARN of the layer version."""
|
|
86
|
+
return self._data["LayerVersionArn"]
|
|
87
|
+
|
|
88
|
+
@property
|
|
89
|
+
def version(self) -> int | None:
|
|
90
|
+
"""The version number of the layer."""
|
|
91
|
+
return self._data["Version"]
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def description(self) -> str | None:
|
|
95
|
+
"""The description of the layer version."""
|
|
96
|
+
return self._data.get("Description")
|
|
97
|
+
|
|
98
|
+
@property
|
|
99
|
+
def created_date(self) -> str | None:
|
|
100
|
+
"""The date that the layer version was created (ISO 8601 format)."""
|
|
101
|
+
return self._data.get("CreatedDate")
|
|
102
|
+
|
|
103
|
+
@property
|
|
104
|
+
def compatible_runtimes(self) -> list[str] | None:
|
|
105
|
+
"""The layer's compatible runtimes."""
|
|
106
|
+
return self._data.get("CompatibleRuntimes")
|
|
107
|
+
|
|
108
|
+
@property
|
|
109
|
+
def license_info(self) -> str | None:
|
|
110
|
+
"""The layer's software license."""
|
|
111
|
+
return self._data.get("LicenseInfo")
|
|
112
|
+
|
|
113
|
+
@property
|
|
114
|
+
def compatible_architectures(self) -> list[str] | None:
|
|
115
|
+
"""A list of compatible instruction set architectures."""
|
|
116
|
+
return self._data.get("CompatibleArchitectures")
|
|
117
|
+
|
|
118
|
+
@property
|
|
119
|
+
def has_python_runtime(self) -> bool:
|
|
120
|
+
"""Check if this layer version supports any Python runtime."""
|
|
121
|
+
if not self.compatible_runtimes:
|
|
122
|
+
return False
|
|
123
|
+
return any(runtime.startswith("python") for runtime in self.compatible_runtimes)
|
|
124
|
+
|
|
125
|
+
@property
|
|
126
|
+
def has_nodejs_runtime(self) -> bool:
|
|
127
|
+
"""Check if this layer version supports any Node.js runtime."""
|
|
128
|
+
if not self.compatible_runtimes:
|
|
129
|
+
return False
|
|
130
|
+
return any(runtime.startswith("nodejs") for runtime in self.compatible_runtimes)
|
|
131
|
+
|
|
132
|
+
@property
|
|
133
|
+
def supports_arm64(self) -> bool:
|
|
134
|
+
"""Check if this layer version supports ARM64 architecture."""
|
|
135
|
+
if not self.compatible_architectures:
|
|
136
|
+
return False
|
|
137
|
+
return "arm64" in self.compatible_architectures
|
|
138
|
+
|
|
139
|
+
@property
|
|
140
|
+
def supports_x86_64(self) -> bool:
|
|
141
|
+
"""Check if this layer version supports x86_64 architecture."""
|
|
142
|
+
if not self.compatible_architectures:
|
|
143
|
+
return False
|
|
144
|
+
return "x86_64" in self.compatible_architectures
|
|
145
|
+
|
|
146
|
+
@property
|
|
147
|
+
def core_data(self) -> T_KWARGS:
|
|
148
|
+
"""Extract core data for standardized representation."""
|
|
149
|
+
return {
|
|
150
|
+
"layer_version_arn": self.layer_version_arn,
|
|
151
|
+
"version": self.version,
|
|
152
|
+
"description": self.description,
|
|
153
|
+
"created_date": self.created_date,
|
|
154
|
+
"compatible_runtimes": self.compatible_runtimes,
|
|
155
|
+
"compatible_architectures": self.compatible_architectures,
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
@dataclasses.dataclass(frozen=True)
|
|
160
|
+
class Layer(Base):
|
|
161
|
+
"""
|
|
162
|
+
Represents an AWS Lambda layer.
|
|
163
|
+
|
|
164
|
+
Ref:
|
|
165
|
+
|
|
166
|
+
- `list_layers <https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/lambda/client/list_layers.html>`_
|
|
167
|
+
|
|
168
|
+
:param _data: Raw data structure as returned by AWS SDK:
|
|
169
|
+
|
|
170
|
+
.. code-block:: python
|
|
171
|
+
|
|
172
|
+
{
|
|
173
|
+
'LayerName': 'string',
|
|
174
|
+
'LayerArn': 'string',
|
|
175
|
+
'LatestMatchingVersion': {
|
|
176
|
+
...
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
"""
|
|
180
|
+
|
|
181
|
+
_data: LayersListItemTypeDef = dataclasses.field(default=REQ)
|
|
182
|
+
|
|
183
|
+
@property
|
|
184
|
+
def layer_name(self) -> str:
|
|
185
|
+
"""The name of the layer."""
|
|
186
|
+
return self._data["LayerName"]
|
|
187
|
+
|
|
188
|
+
@property
|
|
189
|
+
def layer_arn(self) -> str:
|
|
190
|
+
"""The Amazon Resource Name (ARN) of the layer."""
|
|
191
|
+
return self._data["LayerArn"]
|
|
192
|
+
|
|
193
|
+
@property
|
|
194
|
+
def latest_matching_version(self) -> LatestMatchingLayerVersion | None:
|
|
195
|
+
"""The latest matching version of the layer."""
|
|
196
|
+
version_data = self._data.get("LatestMatchingVersion")
|
|
197
|
+
if version_data:
|
|
198
|
+
return LatestMatchingLayerVersion(_data=version_data)
|
|
199
|
+
return None
|
|
200
|
+
|
|
201
|
+
@property
|
|
202
|
+
def has_latest_version(self) -> bool:
|
|
203
|
+
"""Check if this layer has a latest matching version."""
|
|
204
|
+
return self.latest_matching_version is not None
|
|
205
|
+
|
|
206
|
+
@property
|
|
207
|
+
def core_data(self) -> T_KWARGS:
|
|
208
|
+
"""Extract core data for standardized representation."""
|
|
209
|
+
return {
|
|
210
|
+
"layer_name": self.layer_name,
|
|
211
|
+
"layer_arn": self.layer_arn,
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
class LayerIterproxy(IterProxy[Layer]):
|
|
216
|
+
"""
|
|
217
|
+
Iterator proxy for collections of Layer objects with enhanced iteration capabilities.
|
|
218
|
+
"""
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
@dataclasses.dataclass(frozen=True)
|
|
222
|
+
class LayerContent(Base):
|
|
223
|
+
"""
|
|
224
|
+
Represents the content details of a Lambda layer version.
|
|
225
|
+
|
|
226
|
+
:param _data: Raw data structure as returned by AWS SDK:
|
|
227
|
+
|
|
228
|
+
.. code-block:: python
|
|
229
|
+
|
|
230
|
+
{
|
|
231
|
+
'Location': 'string',
|
|
232
|
+
'CodeSha256': 'string',
|
|
233
|
+
'CodeSize': 123,
|
|
234
|
+
'SigningProfileVersionArn': 'string',
|
|
235
|
+
'SigningJobArn': 'string'
|
|
236
|
+
}
|
|
237
|
+
"""
|
|
238
|
+
|
|
239
|
+
_data: LayerVersionContentOutputTypeDef = dataclasses.field()
|
|
240
|
+
|
|
241
|
+
@property
|
|
242
|
+
def location(self) -> str | None:
|
|
243
|
+
"""A link to the layer archive in Amazon S3 that is valid for 10 minutes."""
|
|
244
|
+
return self._data.get("Location")
|
|
245
|
+
|
|
246
|
+
@property
|
|
247
|
+
def code_sha256(self) -> str | None:
|
|
248
|
+
"""The SHA-256 hash of the layer archive."""
|
|
249
|
+
return self._data.get("CodeSha256")
|
|
250
|
+
|
|
251
|
+
@property
|
|
252
|
+
def code_size(self) -> int | None:
|
|
253
|
+
"""The size of the layer archive in bytes."""
|
|
254
|
+
return self._data.get("CodeSize")
|
|
255
|
+
|
|
256
|
+
@property
|
|
257
|
+
def signing_profile_version_arn(self) -> str | None:
|
|
258
|
+
"""The Amazon Resource Name (ARN) for a signing profile version."""
|
|
259
|
+
return self._data.get("SigningProfileVersionArn")
|
|
260
|
+
|
|
261
|
+
@property
|
|
262
|
+
def signing_job_arn(self) -> str | None:
|
|
263
|
+
"""The Amazon Resource Name (ARN) of a signing job."""
|
|
264
|
+
return self._data.get("SigningJobArn")
|
|
265
|
+
|
|
266
|
+
@property
|
|
267
|
+
def core_data(self) -> T_KWARGS:
|
|
268
|
+
"""Extract core data for standardized representation."""
|
|
269
|
+
return {
|
|
270
|
+
"location": self.location,
|
|
271
|
+
"code_sha256": self.code_sha256,
|
|
272
|
+
"code_size": self.code_size,
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
@dataclasses.dataclass(frozen=True)
|
|
277
|
+
class LayerVersion(Base):
|
|
278
|
+
"""
|
|
279
|
+
Represents a specific version of an AWS Lambda layer.
|
|
280
|
+
|
|
281
|
+
Ref:
|
|
282
|
+
|
|
283
|
+
- `list_layer_versions <https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/lambda/client/list_layer_versions.html>`_
|
|
284
|
+
- `get_layer_version <https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/lambda/client/get_layer_version.html>`_
|
|
285
|
+
|
|
286
|
+
:param _data: Raw data structure as returned by AWS SDK:
|
|
287
|
+
|
|
288
|
+
.. code-block:: python
|
|
289
|
+
|
|
290
|
+
{
|
|
291
|
+
'LayerVersionArn': 'string',
|
|
292
|
+
'Version': 123,
|
|
293
|
+
'Description': 'string',
|
|
294
|
+
...
|
|
295
|
+
}
|
|
296
|
+
# or (from get_layer_version)
|
|
297
|
+
{
|
|
298
|
+
'Content': {
|
|
299
|
+
'Location': 'string',
|
|
300
|
+
'CodeSha256': 'string',
|
|
301
|
+
'CodeSize': 123,
|
|
302
|
+
'SigningProfileVersionArn': 'string',
|
|
303
|
+
'SigningJobArn': 'string'
|
|
304
|
+
},
|
|
305
|
+
'LayerArn': 'string',
|
|
306
|
+
'LayerVersionArn': 'string',
|
|
307
|
+
'Description': 'string',
|
|
308
|
+
...
|
|
309
|
+
}
|
|
310
|
+
"""
|
|
311
|
+
|
|
312
|
+
# fmt: off
|
|
313
|
+
_data: LayerVersionsListItemTypeDef | GetLayerVersionResponseTypeDef = dataclasses.field(default=REQ)
|
|
314
|
+
# fmt: on
|
|
315
|
+
|
|
316
|
+
@property
|
|
317
|
+
def layer_version_arn(self) -> str:
|
|
318
|
+
"""The ARN of the layer version."""
|
|
319
|
+
return self._data["LayerVersionArn"]
|
|
320
|
+
|
|
321
|
+
@property
|
|
322
|
+
def version(self) -> int:
|
|
323
|
+
"""The version number of the layer."""
|
|
324
|
+
return self._data["Version"]
|
|
325
|
+
|
|
326
|
+
@property
|
|
327
|
+
def description(self) -> str | None:
|
|
328
|
+
"""The description of the layer version."""
|
|
329
|
+
return self._data.get("Description")
|
|
330
|
+
|
|
331
|
+
@property
|
|
332
|
+
def created_date(self) -> str | None:
|
|
333
|
+
"""The date that the layer version was created (ISO 8601 format)."""
|
|
334
|
+
return self._data.get("CreatedDate")
|
|
335
|
+
|
|
336
|
+
@property
|
|
337
|
+
def compatible_runtimes(self) -> list[str] | None:
|
|
338
|
+
"""The layer's compatible runtimes."""
|
|
339
|
+
return self._data.get("CompatibleRuntimes")
|
|
340
|
+
|
|
341
|
+
@property
|
|
342
|
+
def license_info(self) -> str | None:
|
|
343
|
+
"""The layer's software license."""
|
|
344
|
+
return self._data.get("LicenseInfo")
|
|
345
|
+
|
|
346
|
+
@property
|
|
347
|
+
def compatible_architectures(self) -> list[str] | None:
|
|
348
|
+
"""A list of compatible instruction set architectures."""
|
|
349
|
+
return self._data.get("CompatibleArchitectures")
|
|
350
|
+
|
|
351
|
+
@property
|
|
352
|
+
def layer_arn(self) -> str | None:
|
|
353
|
+
"""The ARN of the layer (only available from get_layer_version)."""
|
|
354
|
+
return self._data.get("LayerArn")
|
|
355
|
+
|
|
356
|
+
# Content-related properties (only available from get_layer_version)
|
|
357
|
+
@property
|
|
358
|
+
def content(self) -> LayerContent | None:
|
|
359
|
+
"""Information about the layer's deployment package (only from get_layer_version)."""
|
|
360
|
+
content_data = self._data.get("Content")
|
|
361
|
+
if content_data:
|
|
362
|
+
return LayerContent(_data=content_data)
|
|
363
|
+
return None
|
|
364
|
+
|
|
365
|
+
@property
|
|
366
|
+
def created_datetime(self) -> datetime:
|
|
367
|
+
"""
|
|
368
|
+
Convert the created_date string to a datetime object.
|
|
369
|
+
"""
|
|
370
|
+
dt = datetime.fromisoformat(self.created_date)
|
|
371
|
+
if dt.tzinfo is None:
|
|
372
|
+
dt = dt.replace(tzinfo=timezone.utc)
|
|
373
|
+
return dt
|
|
374
|
+
|
|
375
|
+
@property
|
|
376
|
+
def layer_name(self) -> str:
|
|
377
|
+
"""Extract the layer name from the layer version ARN."""
|
|
378
|
+
return self.layer_version_arn.split(":")[-2]
|
|
379
|
+
|
|
380
|
+
@property
|
|
381
|
+
def has_content_details(self) -> bool:
|
|
382
|
+
"""Check if this layer version includes content details (from get_layer_version)."""
|
|
383
|
+
return self.content is not None
|
|
384
|
+
|
|
385
|
+
# Computed properties for runtime and architecture checks
|
|
386
|
+
@property
|
|
387
|
+
def has_python_runtime(self) -> bool:
|
|
388
|
+
"""Check if this layer version supports any Python runtime."""
|
|
389
|
+
if not self.compatible_runtimes:
|
|
390
|
+
return False
|
|
391
|
+
return any(runtime.startswith("python") for runtime in self.compatible_runtimes)
|
|
392
|
+
|
|
393
|
+
@property
|
|
394
|
+
def has_nodejs_runtime(self) -> bool:
|
|
395
|
+
"""Check if this layer version supports any Node.js runtime."""
|
|
396
|
+
if not self.compatible_runtimes:
|
|
397
|
+
return False
|
|
398
|
+
return any(runtime.startswith("nodejs") for runtime in self.compatible_runtimes)
|
|
399
|
+
|
|
400
|
+
@property
|
|
401
|
+
def has_java_runtime(self) -> bool:
|
|
402
|
+
"""Check if this layer version supports any Java runtime."""
|
|
403
|
+
if not self.compatible_runtimes:
|
|
404
|
+
return False
|
|
405
|
+
return any(runtime.startswith("java") for runtime in self.compatible_runtimes)
|
|
406
|
+
|
|
407
|
+
@property
|
|
408
|
+
def has_dotnet_runtime(self) -> bool:
|
|
409
|
+
"""Check if this layer version supports any .NET runtime."""
|
|
410
|
+
if not self.compatible_runtimes:
|
|
411
|
+
return False
|
|
412
|
+
return any(
|
|
413
|
+
runtime.startswith("dotnetcore") or runtime.startswith("dotnet")
|
|
414
|
+
for runtime in self.compatible_runtimes
|
|
415
|
+
)
|
|
416
|
+
|
|
417
|
+
@property
|
|
418
|
+
def has_go_runtime(self) -> bool:
|
|
419
|
+
"""Check if this layer version supports Go runtime."""
|
|
420
|
+
if not self.compatible_runtimes:
|
|
421
|
+
return False
|
|
422
|
+
return any(runtime.startswith("go") for runtime in self.compatible_runtimes)
|
|
423
|
+
|
|
424
|
+
@property
|
|
425
|
+
def has_ruby_runtime(self) -> bool:
|
|
426
|
+
"""Check if this layer version supports any Ruby runtime."""
|
|
427
|
+
if not self.compatible_runtimes:
|
|
428
|
+
return False
|
|
429
|
+
return any(runtime.startswith("ruby") for runtime in self.compatible_runtimes)
|
|
430
|
+
|
|
431
|
+
@property
|
|
432
|
+
def has_provided_runtime(self) -> bool:
|
|
433
|
+
"""Check if this layer version supports provided runtime."""
|
|
434
|
+
if not self.compatible_runtimes:
|
|
435
|
+
return False
|
|
436
|
+
return any(
|
|
437
|
+
runtime.startswith("provided") for runtime in self.compatible_runtimes
|
|
438
|
+
)
|
|
439
|
+
|
|
440
|
+
@property
|
|
441
|
+
def supports_arm64(self) -> bool:
|
|
442
|
+
"""Check if this layer version supports ARM64 architecture."""
|
|
443
|
+
if not self.compatible_architectures:
|
|
444
|
+
return False
|
|
445
|
+
return "arm64" in self.compatible_architectures
|
|
446
|
+
|
|
447
|
+
@property
|
|
448
|
+
def supports_x86_64(self) -> bool:
|
|
449
|
+
"""Check if this layer version supports x86_64 architecture."""
|
|
450
|
+
if not self.compatible_architectures:
|
|
451
|
+
return False
|
|
452
|
+
return "x86_64" in self.compatible_architectures
|
|
453
|
+
|
|
454
|
+
@property
|
|
455
|
+
def supports_multi_arch(self) -> bool:
|
|
456
|
+
"""Check if this layer version supports multiple architectures."""
|
|
457
|
+
return self.supports_arm64 and self.supports_x86_64
|
|
458
|
+
|
|
459
|
+
@property
|
|
460
|
+
def runtime_count(self) -> int:
|
|
461
|
+
"""Number of compatible runtimes."""
|
|
462
|
+
return len(self.compatible_runtimes) if self.compatible_runtimes else 0
|
|
463
|
+
|
|
464
|
+
@property
|
|
465
|
+
def architecture_count(self) -> int:
|
|
466
|
+
"""Number of compatible architectures."""
|
|
467
|
+
return (
|
|
468
|
+
len(self.compatible_architectures) if self.compatible_architectures else 0
|
|
469
|
+
)
|
|
470
|
+
|
|
471
|
+
@property
|
|
472
|
+
def core_data(self) -> T_KWARGS:
|
|
473
|
+
"""Extract core data for standardized representation."""
|
|
474
|
+
return {
|
|
475
|
+
"layer_version_arn": self.layer_version_arn,
|
|
476
|
+
"layer_arn": self.layer_arn,
|
|
477
|
+
"version": self.version,
|
|
478
|
+
"description": self.description,
|
|
479
|
+
"created_date": self.created_date,
|
|
480
|
+
"compatible_runtimes": self.compatible_runtimes,
|
|
481
|
+
"compatible_architectures": self.compatible_architectures,
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
class LayerVersionIterproxy(IterProxy[LayerVersion]):
|
|
486
|
+
"""
|
|
487
|
+
Iterator proxy for collections of LayerVersion objects with enhanced iteration capabilities.
|
|
488
|
+
"""
|