boto3-assist 0.1.1__py3-none-any.whl → 0.1.3__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.
- boto3_assist/connection_tracker.py +47 -0
- boto3_assist/dynamodb/dynamodb_index.py +18 -6
- boto3_assist/dynamodb/dynamodb_key.py +3 -2
- boto3_assist/dynamodb/dynamodb_model_base.py +8 -0
- boto3_assist/ec2/ec2_connection.py +103 -0
- boto3_assist/environment_services/environment_variables.py +16 -0
- boto3_assist/version.py +1 -1
- {boto3_assist-0.1.1.dist-info → boto3_assist-0.1.3.dist-info}/METADATA +1 -1
- {boto3_assist-0.1.1.dist-info → boto3_assist-0.1.3.dist-info}/RECORD +12 -10
- {boto3_assist-0.1.1.dist-info → boto3_assist-0.1.3.dist-info}/WHEEL +0 -0
- {boto3_assist-0.1.1.dist-info → boto3_assist-0.1.3.dist-info}/licenses/LICENSE-EXPLAINED.txt +0 -0
- {boto3_assist-0.1.1.dist-info → boto3_assist-0.1.3.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Geek Cafe, LLC
|
|
3
|
+
Maintainers: Eric Wilson
|
|
4
|
+
MIT License. See Project Root for the license information.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ConnectionTracker:
|
|
9
|
+
"""
|
|
10
|
+
Tracks Connection Requests.
|
|
11
|
+
Useful in for performance tuning and debugging.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
def __init__(self, service_name: str) -> None:
|
|
15
|
+
self.__connection_couter: int = 0
|
|
16
|
+
self.__service_name: str = service_name
|
|
17
|
+
|
|
18
|
+
def increment_connection(self) -> None:
|
|
19
|
+
"""Increments the connection counter"""
|
|
20
|
+
self.__connection_couter += 1
|
|
21
|
+
|
|
22
|
+
if self.connection_count > 1:
|
|
23
|
+
self.__log_warning(
|
|
24
|
+
f"Your dynamodb connection count is {self.connection_count}. "
|
|
25
|
+
"Under most circumstances you should be able to use the same connection "
|
|
26
|
+
"vs. creating a new one. Connections are expensive in terms of time / latency. "
|
|
27
|
+
"If you are seeing perforance issues, check how and where you are creating your "
|
|
28
|
+
"connections. You should be able to pass the .db connection to your other objects "
|
|
29
|
+
"and reuse your dynamodb boto connections."
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
def decrement_connection(self) -> None:
|
|
33
|
+
"""Decrements the connection counter"""
|
|
34
|
+
self.__connection_couter -= 1
|
|
35
|
+
|
|
36
|
+
@property
|
|
37
|
+
def connection_count(self) -> int:
|
|
38
|
+
"""Returns the current connection count"""
|
|
39
|
+
return self.__connection_couter
|
|
40
|
+
|
|
41
|
+
def reset(self) -> None:
|
|
42
|
+
"""Resets the connection counter"""
|
|
43
|
+
self.__connection_couter = 0
|
|
44
|
+
|
|
45
|
+
def __log_warning(self, message: str) -> None:
|
|
46
|
+
"""Logs a warning message"""
|
|
47
|
+
print(f"Warning: {message}")
|
|
@@ -6,7 +6,7 @@ https://github.com/geekcafe/boto3-assist
|
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
9
|
-
from typing import Optional
|
|
9
|
+
from typing import Optional, Any
|
|
10
10
|
from boto3.dynamodb.conditions import (
|
|
11
11
|
ConditionBase,
|
|
12
12
|
Key,
|
|
@@ -110,7 +110,8 @@ class DynamoDBIndex:
|
|
|
110
110
|
*,
|
|
111
111
|
include_sort_key: bool = True,
|
|
112
112
|
condition: str = "begins_with",
|
|
113
|
-
|
|
113
|
+
low_value: Any = None,
|
|
114
|
+
high_value: Any = None,
|
|
114
115
|
# sk_value_2: Optional[str | int | float] = None,
|
|
115
116
|
) -> dict | Key | ConditionBase | ComparisonCondition | Equals:
|
|
116
117
|
"""Get the key for a given index"""
|
|
@@ -129,6 +130,7 @@ class DynamoDBIndex:
|
|
|
129
130
|
key = self._build_query_key(
|
|
130
131
|
include_sort_key=include_sort_key,
|
|
131
132
|
condition=condition,
|
|
133
|
+
low_value=low_value,
|
|
132
134
|
high_value=high_value,
|
|
133
135
|
)
|
|
134
136
|
return key
|
|
@@ -138,7 +140,8 @@ class DynamoDBIndex:
|
|
|
138
140
|
*,
|
|
139
141
|
include_sort_key: bool = True,
|
|
140
142
|
condition: str = "begins_with",
|
|
141
|
-
|
|
143
|
+
low_value: Any = None,
|
|
144
|
+
high_value: Any = None,
|
|
142
145
|
) -> And | Equals:
|
|
143
146
|
"""Get the GSI index name and key"""
|
|
144
147
|
|
|
@@ -146,13 +149,22 @@ class DynamoDBIndex:
|
|
|
146
149
|
self.partition_key.value
|
|
147
150
|
)
|
|
148
151
|
|
|
149
|
-
if
|
|
152
|
+
if (
|
|
153
|
+
include_sort_key
|
|
154
|
+
and self.sort_key.attribute_name
|
|
155
|
+
and (
|
|
156
|
+
self.sort_key.value
|
|
157
|
+
or (low_value is not None and high_value is not None)
|
|
158
|
+
)
|
|
159
|
+
):
|
|
150
160
|
# if self.sk_value_2:
|
|
151
|
-
if high_value:
|
|
161
|
+
if low_value is not None and high_value is not None:
|
|
152
162
|
match condition:
|
|
153
163
|
case "between":
|
|
164
|
+
low = f"{self.sort_key.value}{low_value}"
|
|
165
|
+
high = f"{self.sort_key.value}{high_value}"
|
|
154
166
|
key = key & Key(f"{self.sort_key.attribute_name}").between(
|
|
155
|
-
|
|
167
|
+
low, high
|
|
156
168
|
)
|
|
157
169
|
|
|
158
170
|
else:
|
|
@@ -53,9 +53,10 @@ class DynamoDBKey:
|
|
|
53
53
|
"""
|
|
54
54
|
parts = []
|
|
55
55
|
for key, value in key_value_pairs:
|
|
56
|
+
prefix = f"{key}#" if key else ""
|
|
56
57
|
if value is None:
|
|
57
|
-
parts.append(f"{
|
|
58
|
+
parts.append(f"{prefix}")
|
|
58
59
|
break
|
|
59
60
|
else:
|
|
60
|
-
parts.append(f"{
|
|
61
|
+
parts.append(f"{prefix}{value}")
|
|
61
62
|
return "#".join(parts)
|
|
@@ -130,6 +130,14 @@ class DynamoDBModelBase:
|
|
|
130
130
|
self, include_indexes=include_indexes
|
|
131
131
|
)
|
|
132
132
|
|
|
133
|
+
def to_dictionary(self):
|
|
134
|
+
"""
|
|
135
|
+
Convert the instance to a dictionary without an indexes/keys.
|
|
136
|
+
Usefull for turning an object into a dictionary for serialization.
|
|
137
|
+
This is the same as to_resource_dictionary(include_indexes=False)
|
|
138
|
+
"""
|
|
139
|
+
return DynamoDBSerializer.to_resource_dictionary(self, include_indexes=False)
|
|
140
|
+
|
|
133
141
|
def get_key(self, index_name: str) -> DynamoDBIndex:
|
|
134
142
|
"""Get the index name and key"""
|
|
135
143
|
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Geek Cafe, LLC
|
|
3
|
+
Maintainers: Eric Wilson
|
|
4
|
+
MIT License. See Project Root for the license information.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Optional
|
|
8
|
+
from typing import TYPE_CHECKING
|
|
9
|
+
|
|
10
|
+
from aws_lambda_powertools import Logger
|
|
11
|
+
from boto3_assist.boto3session import Boto3SessionManager
|
|
12
|
+
from boto3_assist.environment_services.environment_variables import (
|
|
13
|
+
EnvironmentVariables,
|
|
14
|
+
)
|
|
15
|
+
from boto3_assist.connection_tracker import ConnectionTracker
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from mypy_boto3_ec2 import Client
|
|
19
|
+
else:
|
|
20
|
+
Client = object
|
|
21
|
+
|
|
22
|
+
SERVICE_NAME = "ec2"
|
|
23
|
+
logger = Logger()
|
|
24
|
+
tracker: ConnectionTracker = ConnectionTracker(service_name=SERVICE_NAME)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class EC2Connection:
|
|
28
|
+
"""DB Environment"""
|
|
29
|
+
|
|
30
|
+
def __init__(
|
|
31
|
+
self,
|
|
32
|
+
*,
|
|
33
|
+
aws_profile: Optional[str] = None,
|
|
34
|
+
aws_region: Optional[str] = None,
|
|
35
|
+
aws_access_key_id: Optional[str] = None,
|
|
36
|
+
aws_secret_access_key: Optional[str] = None,
|
|
37
|
+
) -> None:
|
|
38
|
+
self.aws_profile = aws_profile
|
|
39
|
+
self.aws_region = aws_region
|
|
40
|
+
|
|
41
|
+
self.aws_access_key_id = aws_access_key_id
|
|
42
|
+
self.aws_secret_access_key = aws_secret_access_key
|
|
43
|
+
self.__session: Boto3SessionManager | None = None
|
|
44
|
+
self.__client: Client | None = None
|
|
45
|
+
|
|
46
|
+
self.raise_on_error: bool = True
|
|
47
|
+
|
|
48
|
+
def setup(self, setup_source: Optional[str] = None) -> None:
|
|
49
|
+
"""
|
|
50
|
+
Setup the environment. Automatically called via init.
|
|
51
|
+
You can run setup at anytime with new parameters.
|
|
52
|
+
Args: setup_source: Optional[str] = None
|
|
53
|
+
Defines the source of the setup. Useful for logging.
|
|
54
|
+
Returns: None
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
logger.info(
|
|
58
|
+
{
|
|
59
|
+
"metric_filter": "connection_setup",
|
|
60
|
+
"source": "setup",
|
|
61
|
+
"aws_profile": self.aws_profile,
|
|
62
|
+
"aws_region": self.aws_region,
|
|
63
|
+
"setup_source": setup_source,
|
|
64
|
+
}
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
# lazy load the session
|
|
68
|
+
self.__session = Boto3SessionManager(
|
|
69
|
+
service_name=SERVICE_NAME,
|
|
70
|
+
aws_profile=self.aws_profile,
|
|
71
|
+
aws_region=self.aws_region or EnvironmentVariables.AWS.region(),
|
|
72
|
+
aws_access_key_id=self.aws_access_key_id
|
|
73
|
+
or EnvironmentVariables.AWS.aws_access_key_id(),
|
|
74
|
+
aws_secret_access_key=self.aws_secret_access_key
|
|
75
|
+
or EnvironmentVariables.AWS.aws_secret_access_key(),
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
tracker.increment_connection()
|
|
79
|
+
|
|
80
|
+
self.raise_on_error = EnvironmentVariables.AWS.DynamoDB.raise_on_error_setting()
|
|
81
|
+
|
|
82
|
+
@property
|
|
83
|
+
def session(self) -> Boto3SessionManager:
|
|
84
|
+
"""Session"""
|
|
85
|
+
if self.__session is None:
|
|
86
|
+
self.setup(setup_source="session init")
|
|
87
|
+
return self.__session
|
|
88
|
+
|
|
89
|
+
@property
|
|
90
|
+
def client(self) -> Client:
|
|
91
|
+
"""Client Connection"""
|
|
92
|
+
if self.__client is None:
|
|
93
|
+
logger.info("Creating Client")
|
|
94
|
+
self.__client = self.session.client
|
|
95
|
+
|
|
96
|
+
if self.raise_on_error and self.__client is None:
|
|
97
|
+
raise RuntimeError("Client is not available")
|
|
98
|
+
return self.__client
|
|
99
|
+
|
|
100
|
+
@client.setter
|
|
101
|
+
def client(self, value: Client):
|
|
102
|
+
logger.info("Setting Client")
|
|
103
|
+
self.__client = value
|
|
@@ -83,6 +83,22 @@ class EnvironmentVariables:
|
|
|
83
83
|
)
|
|
84
84
|
return value
|
|
85
85
|
|
|
86
|
+
@staticmethod
|
|
87
|
+
def aws_access_key_id() -> str | None:
|
|
88
|
+
"""
|
|
89
|
+
The aws_access_key_id. Often used for local development.
|
|
90
|
+
"""
|
|
91
|
+
value = os.getenv("ACCESS_KEY_ID")
|
|
92
|
+
return value
|
|
93
|
+
|
|
94
|
+
@staticmethod
|
|
95
|
+
def aws_secret_access_key() -> str | None:
|
|
96
|
+
"""
|
|
97
|
+
The aws_secret_access_key. Often used for local development.
|
|
98
|
+
"""
|
|
99
|
+
value = os.getenv("SECRET_ACCESS_KEY")
|
|
100
|
+
return value
|
|
101
|
+
|
|
86
102
|
class SES:
|
|
87
103
|
"""SES Settings"""
|
|
88
104
|
|
boto3_assist/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = '0.1.
|
|
1
|
+
__version__ = '0.1.3'
|
|
@@ -1,28 +1,30 @@
|
|
|
1
1
|
boto3_assist/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
2
|
boto3_assist/boto3session.py,sha256=J20E2lkqJOaey4Ohi-xRe2xABj7QsA8DrggzK29-5es,6415
|
|
3
|
-
boto3_assist/
|
|
3
|
+
boto3_assist/connection_tracker.py,sha256=k59-7CdEvo5Slab80wwYz65sE1-sxVP1-wpQhZZXBZo,1632
|
|
4
|
+
boto3_assist/version.py,sha256=uZsygMXMKRw-7qhWojAjnpm8GFPXU92xW6XA8O5GwFY,22
|
|
4
5
|
boto3_assist/dynamodb/dynamodb.py,sha256=jU4R__5jjI1CmH9xVNUeU8PICD2dtbQ2CYUFKMRw0P0,14561
|
|
5
6
|
boto3_assist/dynamodb/dynamodb_connection.py,sha256=JMCmWOsMzy45rikGl3Z2xqlG2vUTEKSYqi6dpsfJ750,4418
|
|
6
7
|
boto3_assist/dynamodb/dynamodb_connection_tracker.py,sha256=nTNQ99sIidDoLMhMbBju2umgLmcttsmnvmd_DMy_J9M,1582
|
|
7
8
|
boto3_assist/dynamodb/dynamodb_helpers.py,sha256=ajpTJ5bJOm9PDgE2Zx9p2zkTRFV4xswqJRS81SOTn1s,12198
|
|
8
9
|
boto3_assist/dynamodb/dynamodb_importer.py,sha256=8SlT2W03Dvb3LIs6xqtzXP4IShyv655PgMCDNr4kmPk,2559
|
|
9
|
-
boto3_assist/dynamodb/dynamodb_index.py,sha256=
|
|
10
|
+
boto3_assist/dynamodb/dynamodb_index.py,sha256=LRQgSci222s-pU-JXgnaAoOa71ABX9h3uJPeCVPl1GE,6315
|
|
10
11
|
boto3_assist/dynamodb/dynamodb_iservice.py,sha256=2AuaKxt7DUZbB-GpBBtPtPMpAlgZkumkAldm8vy7-sg,701
|
|
11
|
-
boto3_assist/dynamodb/dynamodb_key.py,sha256=
|
|
12
|
-
boto3_assist/dynamodb/dynamodb_model_base.py,sha256=
|
|
12
|
+
boto3_assist/dynamodb/dynamodb_key.py,sha256=X3I3gUPx2T858vjRDi9SN8qn8ez5UJUo0vZiKBeeUWg,1776
|
|
13
|
+
boto3_assist/dynamodb/dynamodb_model_base.py,sha256=IIcqdMN1SMvaDAvN2x1j8FMUPyVp8SdH8Vai8Qr4Nfs,11308
|
|
13
14
|
boto3_assist/dynamodb/dynamodb_model_base_interfaces.py,sha256=yT4zDRI8vP15WVOHnCvY3FsEy_QSIta5-bnUby70Xow,747
|
|
14
15
|
boto3_assist/dynamodb/dynamodb_reindexer.py,sha256=_I-W7Ply-82fRHnhsRZuquRYxEIXubuWGq7E7B4Pa7I,6204
|
|
15
16
|
boto3_assist/dynamodb/readme.md,sha256=wNMzdRwk0qRV0kE88UUYnJos3pEK0HNjEIVkq2PATf8,1490
|
|
16
17
|
boto3_assist/dynamodb/troubleshooting.md,sha256=uGpBaBUt_MyzjzwFOLOe0udTgcvaOpiTFxfj7ilLNkM,136
|
|
18
|
+
boto3_assist/ec2/ec2_connection.py,sha256=KN1AivKY6yYpx_AjmaA3aQUZtUwKIvWk4FO8OPq1aTY,3182
|
|
17
19
|
boto3_assist/environment_services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
20
|
boto3_assist/environment_services/environment_loader.py,sha256=aW-PvlNi8EuavKPXDAi5txLbJFVRkBpkFIgmnR0OWDw,1581
|
|
19
|
-
boto3_assist/environment_services/environment_variables.py,sha256=
|
|
21
|
+
boto3_assist/environment_services/environment_variables.py,sha256=29ujkcFdgVgDgTK_pcVkpcFofEOYTbMXYyRim5vLj-k,6691
|
|
20
22
|
boto3_assist/utilities/datetime_utility.py,sha256=TbqGQkJDTahqvaZAIV550nhYnW1Bsq0Hdu3Go6P4RRs,10282
|
|
21
23
|
boto3_assist/utilities/logging_utility.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
22
24
|
boto3_assist/utilities/serialization_utility.py,sha256=s_QQRIhtwIE7xN5nU13mNk2wtWyErBX_Sg7n0gbHj-M,4308
|
|
23
25
|
boto3_assist/utilities/string_utility.py,sha256=w8l063UT3GE48tuJopETyZrjG4CgAzWkyDWMAYMg5Og,7432
|
|
24
|
-
boto3_assist-0.1.
|
|
25
|
-
boto3_assist-0.1.
|
|
26
|
-
boto3_assist-0.1.
|
|
27
|
-
boto3_assist-0.1.
|
|
28
|
-
boto3_assist-0.1.
|
|
26
|
+
boto3_assist-0.1.3.dist-info/METADATA,sha256=xeuPDWUGFeqRDPD_rCtuZENt7b0-RU-e8SoPbZigwns,1804
|
|
27
|
+
boto3_assist-0.1.3.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
|
28
|
+
boto3_assist-0.1.3.dist-info/licenses/LICENSE-EXPLAINED.txt,sha256=WFREvTpfTjPjDHpOLADxJpCKpIla3Ht87RUUGii4ODU,606
|
|
29
|
+
boto3_assist-0.1.3.dist-info/licenses/LICENSE.txt,sha256=PXDhFWS5L5aOTkVhNvoitHKbAkgxqMI2uUPQyrnXGiI,1105
|
|
30
|
+
boto3_assist-0.1.3.dist-info/RECORD,,
|
|
File without changes
|
{boto3_assist-0.1.1.dist-info → boto3_assist-0.1.3.dist-info}/licenses/LICENSE-EXPLAINED.txt
RENAMED
|
File without changes
|
|
File without changes
|