awsimple 2.2.6__py3-none-any.whl → 2.3.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/__version__.py CHANGED
@@ -1,7 +1,7 @@
1
1
  __application_name__ = "awsimple"
2
2
  __title__ = __application_name__
3
3
  __author__ = "abel"
4
- __version__ = "2.2.6"
4
+ __version__ = "2.3.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/aws.py CHANGED
@@ -56,7 +56,6 @@ class AWSAccess:
56
56
  self.session = boto3.session.Session(**kwargs)
57
57
 
58
58
  if is_mock():
59
-
60
59
  # moto mock AWS
61
60
  for aws_key in ["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_SECURITY_TOKEN", "AWS_SESSION_TOKEN"]:
62
61
  self._aws_keys_save[aws_key] = os.environ.get(aws_key) # will be None if not set
@@ -78,12 +77,15 @@ class AWSAccess:
78
77
  self._moto_mock = moto_mock()
79
78
  self._moto_mock.start()
80
79
  region = "us-east-1"
81
- if self.resource_name == "logs":
82
- # logs don't have resource
80
+ if self.resource_name == "logs" or self.resource_name is None:
81
+ # logs don't have a resource
83
82
  self.resource = None
84
83
  else:
85
84
  self.resource = boto3.resource(self.resource_name, region_name=region) # type: ignore
86
- self.client = boto3.client(self.resource_name, region_name=region) # type: ignore
85
+ if self.resource_name is None:
86
+ self.client = None
87
+ else:
88
+ self.client = boto3.client(self.resource_name, region_name=region) # type: ignore
87
89
  if self.resource_name == "s3":
88
90
  assert self.resource is not None
89
91
  self.resource.create_bucket(Bucket="testawsimple") # todo: put this in the test code
@@ -154,9 +156,7 @@ class AWSAccess:
154
156
  return self._moto_mock is not None
155
157
 
156
158
  def __del__(self):
157
-
158
159
  if self._moto_mock is not None:
159
-
160
160
  # if mocking, put everything back
161
161
 
162
162
  for aws_key, value in self._aws_keys_save.items():
awsimple/cache.py CHANGED
@@ -69,7 +69,6 @@ def lru_cache_write(new_data: Union[Path, bytes], cache_dir: Path, cache_file_na
69
69
  log.info(f"{new_data=} {new_size=} is larger than the cache itself {max_cache_size=}")
70
70
  is_room = False # new file will never fit so don't try to evict to make room for it
71
71
  else:
72
-
73
72
  cache_size = get_directory_size(cache_dir)
74
73
  overage = (cache_size + new_size) - max_cache_size
75
74
 
awsimple/dynamodb.py CHANGED
@@ -193,6 +193,13 @@ class DBItemNotFound(AWSimpleException):
193
193
  return f"{self.key=} {self.message}"
194
194
 
195
195
 
196
+ class TableNotFound(AWSimpleException):
197
+ def __init__(self, table_name: str):
198
+ self.table_name = table_name
199
+ self.message = f'Table "{self.table_name}" not found'
200
+ super().__init__(self.message)
201
+
202
+
196
203
  @typechecked()
197
204
  def _is_valid_db_pickled_file(file_path: Path, cache_life: Union[float, int, None]) -> bool:
198
205
  is_valid = file_path.exists() and getsize(str(file_path)) > 0
@@ -513,13 +520,22 @@ class DynamoDBAccess(CacheAccess):
513
520
  @lru_cache()
514
521
  def get_primary_keys_dict(self) -> Dict[KeyType, str]:
515
522
  """
516
- Get the table's primary keys.
523
+ Get the table's primary keys. Raise TableNotFound if table does not exist.
517
524
 
518
525
  :return: a dict with the primary key partition key and (optionally) sort key
519
526
  """
520
527
 
521
528
  assert self.resource is not None
522
- return self._get_keys_from_schema(self.resource.Table(self.table_name).key_schema)
529
+ try:
530
+ table = self.resource.Table(self.table_name)
531
+ except ClientError as e:
532
+ if e.response["Error"]["Code"] == "ResourceNotFoundException":
533
+ raise TableNotFound(self.table_name)
534
+ else:
535
+ raise
536
+ key_schema = table.key_schema
537
+ keys = self._get_keys_from_schema(key_schema)
538
+ return keys
523
539
 
524
540
  @lru_cache()
525
541
  def get_primary_partition_key(self) -> str:
@@ -768,7 +784,6 @@ class DynamoDBAccess(CacheAccess):
768
784
  def upsert_item(
769
785
  self, partition_key: str = None, partition_value: Union[str, int] = None, sort_key: Union[str, None] = None, sort_value: Union[str, int, None] = None, item: Union[dict, None] = None
770
786
  ):
771
-
772
787
  """
773
788
  Upsert (update or insert) table item
774
789
 
awsimple/dynamodb_miv.py CHANGED
@@ -66,7 +66,6 @@ class DynamoDBMIVUI(DynamoDBAccess):
66
66
 
67
67
  # Determine new miv. The miv is an int to avoid comparison or specification problems that can arise with floats. For example, when it comes time to delete an item.
68
68
  if time_us is None:
69
-
70
69
  # get the miv for the existing entries
71
70
  partition_key = self.get_primary_partition_key()
72
71
  partition_value = item[partition_key]
awsimple/s3.py CHANGED
@@ -445,7 +445,6 @@ class S3Access(CacheAccess):
445
445
  assert self.resource is not None
446
446
  bucket_resource = self.resource.Bucket(self.bucket_name)
447
447
  if self.object_exists(s3_key):
448
-
449
448
  bucket_object = bucket_resource.Object(s3_key)
450
449
  assert isinstance(self.bucket_name, str) # mainly for mypy
451
450
  s3_object_metadata = S3ObjectMetadata(
awsimple/sqs.py CHANGED
@@ -136,7 +136,6 @@ class SQSAccess(AWSAccess):
136
136
  return nominal_work_time
137
137
 
138
138
  def calculate_visibility_timeout(self) -> int:
139
-
140
139
  if self.user_provided_timeout is None:
141
140
  if self.immediate_delete:
142
141
  visibility_timeout = self.immediate_delete_timeout # we immediately delete the message so this doesn't need to be very long
@@ -155,7 +154,6 @@ class SQSAccess(AWSAccess):
155
154
 
156
155
  @typechecked()
157
156
  def _receive(self, max_number_of_messages_parameter: int = None) -> List[SQSMessage]:
158
-
159
157
  if self.user_provided_timeout is None and not self.immediate_delete:
160
158
  # read in response history (and initialize it if it doesn't exist)
161
159
  try:
@@ -177,7 +175,6 @@ class SQSAccess(AWSAccess):
177
175
  call_wait_time = self.sqs_call_wait_time # first time through may be long poll, but after that it's a short poll
178
176
 
179
177
  while continue_to_receive:
180
-
181
178
  aws_messages = None
182
179
 
183
180
  if max_number_of_messages_parameter is None:
@@ -186,7 +183,6 @@ class SQSAccess(AWSAccess):
186
183
  max_number_of_messages = max_number_of_messages_parameter - len(messages) # how many left to do
187
184
 
188
185
  try:
189
-
190
186
  aws_messages = self._get_queue().receive_messages(
191
187
  MaxNumberOfMessages=min(max_number_of_messages, aws_sqs_max_messages), VisibilityTimeout=self.calculate_visibility_timeout(), WaitTimeSeconds=call_wait_time
192
188
  )
@@ -195,7 +191,6 @@ class SQSAccess(AWSAccess):
195
191
  if self.immediate_delete:
196
192
  m.delete()
197
193
  elif self.user_provided_timeout is None:
198
-
199
194
  # keep history of message processing times for user deletes, by AWS's message id
200
195
  self.response_history[m.message_id] = [time.time(), None] # start (finish will be filled in upon delete)
201
196
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: awsimple
3
- Version: 2.2.6
3
+ Version: 2.3.0
4
4
  Summary: Simple AWS API for S3, DynamoDB, SNS, and SQS
5
5
  Home-page: https://github.com/jamesabel/awsimple
6
6
  Download-URL: https://github.com/jamesabel/awsimple
@@ -13,7 +13,7 @@ Description-Content-Type: text/markdown
13
13
  License-File: LICENSE
14
14
  License-File: LICENSE.txt
15
15
  Requires-Dist: boto3
16
- Requires-Dist: typeguard
16
+ Requires-Dist: typeguard (<3)
17
17
  Requires-Dist: hashy (>=0.1.1)
18
18
  Requires-Dist: dictim
19
19
  Requires-Dist: appdirs
@@ -0,0 +1,18 @@
1
+ awsimple/__init__.py,sha256=8NChv83C13WICTMbi89I78fAKSE3UQtcGq4YwXAl3OU,826
2
+ awsimple/__version__.py,sha256=ou_bUclq3bwRO56DBjSReyO_DcrTw2lpPq15hmhVUQw,323
3
+ awsimple/aws.py,sha256=006liY2mXwbPu5kl3-nCgmkpMN7pBqEDetqM1eNbXWU,6365
4
+ awsimple/cache.py,sha256=5dYf7bh1Dr_pFbkHck4Ym8zrffctv0ERhGJwieRHQH8,7137
5
+ awsimple/dynamodb.py,sha256=zCinM2oE26Rtl8Vb9kp8UmgDV1HiVXzSfMiJO-XS8aA,35424
6
+ awsimple/dynamodb_miv.py,sha256=FcbEn2VbrYxQcgQKqFoWFqVwAkoqJpwZ4Nr5guXgGXM,4619
7
+ awsimple/logs.py,sha256=A2RmTT90pfFTthfENd7GSsEHSIBJXO8ICHPdA7sEsHY,4278
8
+ awsimple/mock.py,sha256=32CNU656uC3PBhjCJ4R-WBTtHbSl6VNVkpN8G8XDvsQ,199
9
+ awsimple/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ awsimple/s3.py,sha256=uMEz6NN9hXOfsQNUNJ2YOuKGKlT2xqZ5btJ9zsCHBrY,23243
11
+ awsimple/sns.py,sha256=LjKj-UxPdfRDQfN10jU_ULjnlEqLmHcuqfRIKX9lkZo,3266
12
+ awsimple/sqs.py,sha256=yf8a9jGbYzdajeDU3rARFFYoMb3jQ-YJAVNvw4WscW8,13007
13
+ awsimple-2.3.0.dist-info/LICENSE,sha256=d956YAgtDaxgxQmccyUk__EfhORZyBjvmJ8pq6zYTxk,1093
14
+ awsimple-2.3.0.dist-info/LICENSE.txt,sha256=d956YAgtDaxgxQmccyUk__EfhORZyBjvmJ8pq6zYTxk,1093
15
+ awsimple-2.3.0.dist-info/METADATA,sha256=SQAOmvSYRqftTUXxK05S4BaUPKnpJmfragonG5oUfmM,4815
16
+ awsimple-2.3.0.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
17
+ awsimple-2.3.0.dist-info/top_level.txt,sha256=mwqCoH_8vAaK6iYioiRbasXmVCQM7AK3grNWOKp2VHE,9
18
+ awsimple-2.3.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.38.4)
2
+ Generator: bdist_wheel (0.40.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,18 +0,0 @@
1
- awsimple/__init__.py,sha256=8NChv83C13WICTMbi89I78fAKSE3UQtcGq4YwXAl3OU,826
2
- awsimple/__version__.py,sha256=MsxrZZ4ZyLep26haDLvH1Fb2CwyaV8ebc2v0DBheVbc,323
3
- awsimple/aws.py,sha256=YuHs_AzsQEgGS-MnDacrLLy6Q4z3XlQ-bfeNZ4nGfNo,6236
4
- awsimple/cache.py,sha256=6CvpQufG7CHi4E3pkn3W9XCic_wM-WzhvDRzncNWWhI,7139
5
- awsimple/dynamodb.py,sha256=qB9EqTGyb0CmS1VmNcKL28HGI08iQxq7mnp4Ic1sajE,34852
6
- awsimple/dynamodb_miv.py,sha256=q2C-PYEwmLdU0qQVDPui4XZ_podrEUSt6gxkPxl09YQ,4621
7
- awsimple/logs.py,sha256=A2RmTT90pfFTthfENd7GSsEHSIBJXO8ICHPdA7sEsHY,4278
8
- awsimple/mock.py,sha256=32CNU656uC3PBhjCJ4R-WBTtHbSl6VNVkpN8G8XDvsQ,199
9
- awsimple/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- awsimple/s3.py,sha256=cDLz3X1SvU2KOUPp1WUIrPJsSue7HIqyAqn7q0seKIE,23245
11
- awsimple/sns.py,sha256=LjKj-UxPdfRDQfN10jU_ULjnlEqLmHcuqfRIKX9lkZo,3266
12
- awsimple/sqs.py,sha256=iTbKiM80V5f3gy6Rej3CdU7qCFNJQfFjz0uAI7BaNDk,13017
13
- awsimple-2.2.6.dist-info/LICENSE,sha256=d956YAgtDaxgxQmccyUk__EfhORZyBjvmJ8pq6zYTxk,1093
14
- awsimple-2.2.6.dist-info/LICENSE.txt,sha256=d956YAgtDaxgxQmccyUk__EfhORZyBjvmJ8pq6zYTxk,1093
15
- awsimple-2.2.6.dist-info/METADATA,sha256=9BTI2gbINrxmxf21UpK7V8luv9deI_fRCnCIdbTWKsE,4810
16
- awsimple-2.2.6.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
17
- awsimple-2.2.6.dist-info/top_level.txt,sha256=mwqCoH_8vAaK6iYioiRbasXmVCQM7AK3grNWOKp2VHE,9
18
- awsimple-2.2.6.dist-info/RECORD,,