awsimple 3.10.0__py3-none-any.whl → 3.11.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.
Potentially problematic release.
This version of awsimple might be problematic. Click here for more details.
- awsimple/__init__.py +1 -0
- awsimple/__version__.py +1 -1
- awsimple/dynamodb.py +39 -2
- awsimple/exceptions.py +16 -0
- {awsimple-3.10.0.dist-info → awsimple-3.11.0.dist-info}/METADATA +1 -1
- {awsimple-3.10.0.dist-info → awsimple-3.11.0.dist-info}/RECORD +10 -9
- {awsimple-3.10.0.dist-info → awsimple-3.11.0.dist-info}/WHEEL +0 -0
- {awsimple-3.10.0.dist-info → awsimple-3.11.0.dist-info}/licenses/LICENSE +0 -0
- {awsimple-3.10.0.dist-info → awsimple-3.11.0.dist-info}/licenses/LICENSE.txt +0 -0
- {awsimple-3.10.0.dist-info → awsimple-3.11.0.dist-info}/top_level.txt +0 -0
awsimple/__init__.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from .__version__ import __application_name__, __version__, __author__, __title__
|
|
2
2
|
from .mock import use_moto_mock_env_var, is_mock, use_localstack_env_var, is_using_localstack
|
|
3
|
+
from .exceptions import DynamoDBItemAlreadyExists
|
|
3
4
|
from .aws import AWSAccess, AWSimpleException, boto_error_to_string
|
|
4
5
|
from .cache import get_disk_free, get_directory_size, lru_cache_write, CacheAccess, CACHE_DIR_ENV_VAR
|
|
5
6
|
from .dynamodb import DynamoDBAccess, dict_to_dynamodb, DBItemNotFound, DynamoDBTableNotFound, dynamodb_to_json, dynamodb_to_dict, QuerySelection, DictKey, convert_serializable_special_cases
|
awsimple/__version__.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
__application_name__ = "awsimple"
|
|
2
2
|
__title__ = __application_name__
|
|
3
3
|
__author__ = "abel"
|
|
4
|
-
__version__ = "3.
|
|
4
|
+
__version__ = "3.11.0"
|
|
5
5
|
__author_email__ = "j@abel.co"
|
|
6
6
|
__url__ = "https://github.com/jamesabel/awsimple"
|
|
7
7
|
__download_url__ = "https://github.com/jamesabel/awsimple"
|
awsimple/dynamodb.py
CHANGED
|
@@ -28,7 +28,8 @@ from typeguard import typechecked
|
|
|
28
28
|
from dictim import dictim # type: ignore
|
|
29
29
|
from yasf import sf
|
|
30
30
|
|
|
31
|
-
from
|
|
31
|
+
from . import CacheAccess, __application_name__, AWSimpleException
|
|
32
|
+
from .exceptions import DynamoDBItemAlreadyExists
|
|
32
33
|
|
|
33
34
|
# don't require pillow, but convert images with it if it exists
|
|
34
35
|
pil_exists = False
|
|
@@ -219,6 +220,10 @@ def _is_valid_db_pickled_file(file_path: Path, cache_life: Union[float, int, Non
|
|
|
219
220
|
|
|
220
221
|
|
|
221
222
|
class DynamoDBAccess(CacheAccess):
|
|
223
|
+
"""
|
|
224
|
+
AWS DynamoDB access
|
|
225
|
+
"""
|
|
226
|
+
|
|
222
227
|
@typechecked()
|
|
223
228
|
def __init__(self, table_name: Union[str, None] = None, **kwargs):
|
|
224
229
|
"""
|
|
@@ -733,6 +738,36 @@ class DynamoDBAccess(CacheAccess):
|
|
|
733
738
|
except self.client.exceptions.ResourceNotFoundException:
|
|
734
739
|
raise DynamoDBTableNotFound(str(self.table_name))
|
|
735
740
|
|
|
741
|
+
def put_item_if_not_exists(self, item: dict):
|
|
742
|
+
"""
|
|
743
|
+
Put (write) a DynamoDB table dict item if it doesn't already exist. If the item already exists, it is not modified and DynamoDBItemAlreadyExists is raised.
|
|
744
|
+
|
|
745
|
+
:param item: item
|
|
746
|
+
"""
|
|
747
|
+
assert self.resource is not None
|
|
748
|
+
primary_partition_key = self.get_primary_partition_key()
|
|
749
|
+
primary_sort_key = self.get_primary_sort_key()
|
|
750
|
+
try:
|
|
751
|
+
table = self.resource.Table(self.table_name)
|
|
752
|
+
if primary_sort_key is None:
|
|
753
|
+
table.put_item(Item=item, ConditionExpression="attribute_not_exists(#pk)", ExpressionAttributeNames={"#pk": primary_partition_key})
|
|
754
|
+
else:
|
|
755
|
+
table.put_item(
|
|
756
|
+
Item=item,
|
|
757
|
+
ConditionExpression="attribute_not_exists(#pk) AND attribute_not_exists(#sk)",
|
|
758
|
+
ExpressionAttributeNames={"#pk": primary_partition_key, "#sk": primary_sort_key},
|
|
759
|
+
)
|
|
760
|
+
self.metadata_table.update_table_mtime()
|
|
761
|
+
already_exists = False
|
|
762
|
+
except self.client.exceptions.ResourceNotFoundException:
|
|
763
|
+
raise DynamoDBTableNotFound(str(self.table_name))
|
|
764
|
+
except self.client.exceptions.ConditionalCheckFailedException:
|
|
765
|
+
already_exists = True
|
|
766
|
+
if already_exists:
|
|
767
|
+
primary_partition_value = str(item.get(primary_partition_key, ""))
|
|
768
|
+
primary_sort_value = str(item.get(primary_sort_key, ""))
|
|
769
|
+
raise DynamoDBItemAlreadyExists(str(self.table_name), primary_partition_value, primary_sort_value)
|
|
770
|
+
|
|
736
771
|
# cant' do a @typechecked() since optional item requires a single type
|
|
737
772
|
def get_item(
|
|
738
773
|
self, partition_key: Union[str, None] = None, partition_value: Union[str, int, None] = None, sort_key: Union[str, None] = None, sort_value: Union[str, int, None] = None
|
|
@@ -886,6 +921,9 @@ class DynamoDBAccess(CacheAccess):
|
|
|
886
921
|
if len(filtered_row) > 0:
|
|
887
922
|
filtered_rows.append(filtered_row)
|
|
888
923
|
field_names = sorted(field_names_set)
|
|
924
|
+
primary_partition_key = self.get_primary_partition_key()
|
|
925
|
+
primary_sort_key = self.get_primary_sort_key()
|
|
926
|
+
filtered_rows.sort(key=lambda x: (x[primary_partition_key], x.get(primary_sort_key))) # sort by primary partition key, then sort key if it exists
|
|
889
927
|
|
|
890
928
|
file_path.parent.mkdir(parents=True, exist_ok=True)
|
|
891
929
|
with open(file_path, "w", newline="") as csvfile:
|
|
@@ -897,7 +935,6 @@ class DynamoDBAccess(CacheAccess):
|
|
|
897
935
|
log.info(f"wrote {len(filtered_rows)} rows to {file_path}")
|
|
898
936
|
|
|
899
937
|
|
|
900
|
-
|
|
901
938
|
metadata_table_name = f"__{__application_name__}_metadata__"
|
|
902
939
|
|
|
903
940
|
|
awsimple/exceptions.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
class AWSimpleExceptionBase(Exception):
|
|
2
|
+
"""Base exception for AWSimple errors."""
|
|
3
|
+
|
|
4
|
+
pass
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class DynamoDBItemAlreadyExists(AWSimpleExceptionBase):
|
|
8
|
+
"""Raised when an item already exists in DynamoDB."""
|
|
9
|
+
|
|
10
|
+
def __init__(self, table_name: str, primary_partition_value: str, primary_sort_value: str):
|
|
11
|
+
if len(primary_sort_value) < 1:
|
|
12
|
+
sort_message = ""
|
|
13
|
+
else:
|
|
14
|
+
sort_message = f" and {primary_sort_value=}"
|
|
15
|
+
message = f"Item with {primary_partition_value=}{sort_message} already exists in table {table_name}"
|
|
16
|
+
super().__init__(message)
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
awsimple/__init__.py,sha256=
|
|
2
|
-
awsimple/__version__.py,sha256=
|
|
1
|
+
awsimple/__init__.py,sha256=X7MV9cg5V1dYf86tf3TonaU-LMQWenPIW2PnjxoXYB4,1015
|
|
2
|
+
awsimple/__version__.py,sha256=ey8QJTcIT2kFHhegrTZ0d01xX-GQD2kvye8fTm8hdp4,324
|
|
3
3
|
awsimple/aws.py,sha256=NbRu1v_J5j2-pcefNZ5Xggii3mM9nHpeHMz9L9K9r-U,7653
|
|
4
4
|
awsimple/cache.py,sha256=_LvPx76215t8KhAJOin6Pe2b4lWpB6kbKpdzgR4FeA4,7206
|
|
5
|
-
awsimple/dynamodb.py,sha256=
|
|
5
|
+
awsimple/dynamodb.py,sha256=FZTk_BWOZYr3wYW7jfIgQOYaKQ_SMRMfozAT1UbMXiM,42662
|
|
6
6
|
awsimple/dynamodb_miv.py,sha256=4xPxQDYkIM-BVDGyAre6uqwJHsxguEbHbof8ztt-V7g,4645
|
|
7
|
+
awsimple/exceptions.py,sha256=dZQn8BKmZVlIl2-MIT5SAHRcwYK_bjzzWeG1AFbDUEg,609
|
|
7
8
|
awsimple/logs.py,sha256=s9FhdDFWjfxGCVDx-FNTPgJ-YN1AOAgz4HNxTVfRARE,4108
|
|
8
9
|
awsimple/mock.py,sha256=eScbnxFF9xAosOAsL-NZgp_P-fezB6StQMkb85Y3TNo,574
|
|
9
10
|
awsimple/platform.py,sha256=TObvLIVgRGh-Mh4ZCxFfxAmrn8KNMHktr6XkDZX8JYE,376
|
|
@@ -12,9 +13,9 @@ awsimple/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
12
13
|
awsimple/s3.py,sha256=ydYLDj51b38lYI6LsJlc4i0PDj2vnWBuSkzdRKcWAUg,23858
|
|
13
14
|
awsimple/sns.py,sha256=T_FyN8eSmBPo213HOfB3UBlMrvtBK768IaRo_ks-7do,3526
|
|
14
15
|
awsimple/sqs.py,sha256=9ZY7161CpmYpcxlCFIfW8bvMn9SGl4cgGR79I4MFLDk,17281
|
|
15
|
-
awsimple-3.
|
|
16
|
-
awsimple-3.
|
|
17
|
-
awsimple-3.
|
|
18
|
-
awsimple-3.
|
|
19
|
-
awsimple-3.
|
|
20
|
-
awsimple-3.
|
|
16
|
+
awsimple-3.11.0.dist-info/licenses/LICENSE,sha256=d956YAgtDaxgxQmccyUk__EfhORZyBjvmJ8pq6zYTxk,1093
|
|
17
|
+
awsimple-3.11.0.dist-info/licenses/LICENSE.txt,sha256=d956YAgtDaxgxQmccyUk__EfhORZyBjvmJ8pq6zYTxk,1093
|
|
18
|
+
awsimple-3.11.0.dist-info/METADATA,sha256=eIOptt5qOoQFZMW6qipEzGLbIuBhA46K3JZNqSabPq0,6641
|
|
19
|
+
awsimple-3.11.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
20
|
+
awsimple-3.11.0.dist-info/top_level.txt,sha256=mwqCoH_8vAaK6iYioiRbasXmVCQM7AK3grNWOKp2VHE,9
|
|
21
|
+
awsimple-3.11.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|