boto3-assist 0.1.13__tar.gz → 0.1.14__tar.gz

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 (81) hide show
  1. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/PKG-INFO +1 -1
  2. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/pyproject.toml +1 -1
  3. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/src/boto3_assist/dynamodb/dynamodb_key.py +3 -1
  4. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/src/boto3_assist/dynamodb/dynamodb_model_base.py +22 -2
  5. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/src/boto3_assist/dynamodb/dynamodb_reserved_words.py +1 -1
  6. boto3_assist-0.1.14/src/boto3_assist/version.py +1 -0
  7. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/tests/dynamodb/dynamodb_model_base_test.py +34 -0
  8. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/tests/dynamodb/dynamodb_model_projections_test.py +22 -0
  9. boto3_assist-0.1.14/tests/dynamodb/dynamodb_model_serializtion_test.py +51 -0
  10. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/tests/dynamodb/models/user_model.py +4 -4
  11. boto3_assist-0.1.13/src/boto3_assist/version.py +0 -1
  12. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/.env.development +0 -0
  13. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/.env.docker +0 -0
  14. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/.env.docker.001 +0 -0
  15. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/.env.docker.nosql.workbench +0 -0
  16. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/.gitignore +0 -0
  17. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/.vscode/launch.json +0 -0
  18. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/.vscode/settings.json +0 -0
  19. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/.vscode/tasks.json +0 -0
  20. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/LICENSE-EXPLAINED.txt +0 -0
  21. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/LICENSE.txt +0 -0
  22. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/README.md +0 -0
  23. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/aws_regions_with_status.csv +0 -0
  24. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/aws_regions_with_status.json +0 -0
  25. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/devops/build.py +0 -0
  26. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/devops/readme.md +0 -0
  27. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/examples/__init__.py +0 -0
  28. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/examples/dynamodb/models/order_item_model.py +0 -0
  29. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/examples/dynamodb/models/order_model.py +0 -0
  30. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/examples/dynamodb/models/product_model.py +0 -0
  31. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/examples/dynamodb/models/user_model.py +0 -0
  32. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/examples/dynamodb/models/user_post_model.py +0 -0
  33. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/examples/dynamodb/order_example/main.py +0 -0
  34. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/examples/dynamodb/order_example/products.json +0 -0
  35. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/examples/dynamodb/services/order_item_service.py +0 -0
  36. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/examples/dynamodb/services/order_service.py +0 -0
  37. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/examples/dynamodb/services/product_service.py +0 -0
  38. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/examples/dynamodb/services/table_service.py +0 -0
  39. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/examples/dynamodb/services/user_post_service.py +0 -0
  40. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/examples/dynamodb/services/user_service.py +0 -0
  41. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/examples/dynamodb/services/user_service_client_example.py +0 -0
  42. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/examples/dynamodb/services/user_service_resource_example.py +0 -0
  43. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/examples/dynamodb/user_post_example/main.py +0 -0
  44. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/examples/ec2/regions_report.py +0 -0
  45. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/module-headers.txt +0 -0
  46. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/mypy.ini +0 -0
  47. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/requirements-dev.txt +0 -0
  48. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/requirements.txt +0 -0
  49. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/run-checks.sh +0 -0
  50. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/src/boto3_assist/__init__.py +0 -0
  51. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/src/boto3_assist/boto3session.py +0 -0
  52. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/src/boto3_assist/connection_tracker.py +0 -0
  53. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/src/boto3_assist/dynamodb/dynamodb.py +0 -0
  54. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/src/boto3_assist/dynamodb/dynamodb_connection.py +0 -0
  55. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/src/boto3_assist/dynamodb/dynamodb_connection_tracker.py +0 -0
  56. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/src/boto3_assist/dynamodb/dynamodb_helpers.py +0 -0
  57. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/src/boto3_assist/dynamodb/dynamodb_importer.py +0 -0
  58. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/src/boto3_assist/dynamodb/dynamodb_index.py +0 -0
  59. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/src/boto3_assist/dynamodb/dynamodb_iservice.py +0 -0
  60. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/src/boto3_assist/dynamodb/dynamodb_model_base_interfaces.py +0 -0
  61. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/src/boto3_assist/dynamodb/dynamodb_reindexer.py +0 -0
  62. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/src/boto3_assist/dynamodb/dynamodb_reserved_words.txt +0 -0
  63. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/src/boto3_assist/dynamodb/readme.md +0 -0
  64. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/src/boto3_assist/dynamodb/troubleshooting.md +0 -0
  65. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/src/boto3_assist/ec2/ec2_connection.py +0 -0
  66. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/src/boto3_assist/environment_services/__init__.py +0 -0
  67. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/src/boto3_assist/environment_services/environment_loader.py +0 -0
  68. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/src/boto3_assist/environment_services/environment_variables.py +0 -0
  69. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/src/boto3_assist/utilities/datetime_utility.py +0 -0
  70. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/src/boto3_assist/utilities/logging_utility.py +0 -0
  71. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/src/boto3_assist/utilities/serialization_utility.py +0 -0
  72. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/src/boto3_assist/utilities/string_utility.py +0 -0
  73. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/tests/__init__.py +0 -0
  74. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/tests/__top/__init__.py +0 -0
  75. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/tests/dynamodb/__init__.py +0 -0
  76. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/tests/dynamodb/dynamodb_reindex_test.py +0 -0
  77. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/tests/dynamodb/models/simple_model.py +0 -0
  78. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/tests/examples_test/__init__.py +0 -0
  79. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/tests/examples_test/user_service_test.py +0 -0
  80. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/tests/utilities/__init__.py +0 -0
  81. {boto3_assist-0.1.13 → boto3_assist-0.1.14}/tests/utilities/serialization_utility_test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: boto3_assist
3
- Version: 0.1.13
3
+ Version: 0.1.14
4
4
  Summary: Additional boto3 wrappers to make your life a little easier
5
5
  Author-email: Eric Wilson <boto3-assist@geekcafe.com>
6
6
  License-File: LICENSE-EXPLAINED.txt
@@ -7,7 +7,7 @@ packages = ["src/boto3_assist"]
7
7
 
8
8
  [project]
9
9
  name = "boto3_assist"
10
- version = "0.1.13"
10
+ version = "0.1.14"
11
11
  authors = [
12
12
  { name="Eric Wilson", email="boto3-assist@geekcafe.com" }
13
13
  ]
@@ -59,4 +59,6 @@ class DynamoDBKey:
59
59
  break
60
60
  else:
61
61
  parts.append(f"{prefix}{value}")
62
- return "#".join(parts)
62
+ key_str = "#".join(parts)
63
+
64
+ return key_str
@@ -64,13 +64,21 @@ class DynamoDBModelBase:
64
64
  @exclude_from_serialization
65
65
  def projection_expression(self) -> str | None:
66
66
  """Gets the projection expression"""
67
+ prop_list: List[str] = []
67
68
  if self.__projection_expression is None and self.auto_generate_projections:
68
69
  props = self.to_dictionary()
69
70
  # turn props to a list[str]
70
71
  prop_list = list(props.keys())
72
+ else:
73
+ if self.__projection_expression:
74
+ prop_list = self.__projection_expression.split(",")
75
+ prop_list = [p.strip() for p in prop_list]
76
+
77
+ if len(prop_list) == 0:
78
+ return None
71
79
 
72
- transformed_list = self.__reserved_words.tranform_projections(prop_list)
73
- self.projection_expression = ",".join(transformed_list)
80
+ transformed_list = self.__reserved_words.tranform_projections(prop_list)
81
+ self.projection_expression = ",".join(transformed_list)
74
82
 
75
83
  return self.__projection_expression
76
84
 
@@ -105,6 +113,12 @@ class DynamoDBModelBase:
105
113
  self.projection_expression_attribute_names = (
106
114
  self.__reserved_words.transform_attributes(prop_list)
107
115
  )
116
+ else:
117
+ if self.projection_expression:
118
+ expression_list = self.projection_expression.replace("#", "").split(",")
119
+ self.projection_expression_attribute_names = (
120
+ self.__reserved_words.transform_attributes(expression_list)
121
+ )
108
122
 
109
123
  return self.__projection_expression_attribute_names
110
124
 
@@ -325,6 +339,8 @@ class DynamoDBSerializer:
325
339
 
326
340
  # Add instance variables
327
341
  for attr, value in instance.__dict__.items():
342
+ if str(attr) == "T":
343
+ continue
328
344
  # don't get the private properties
329
345
  if not str(attr).startswith("_"):
330
346
  if value is not None or include_none:
@@ -346,6 +362,10 @@ class DynamoDBSerializer:
346
362
  if exclude:
347
363
  continue
348
364
 
365
+ # Skip TypeVar T or instances of DynamoDBModelBase
366
+ if str(name) == "T":
367
+ continue
368
+
349
369
  # don't get the private properties
350
370
  if not str(name).startswith("_"):
351
371
  value = getattr(instance, name)
@@ -31,7 +31,7 @@ class DynamoDBReservedWords:
31
31
  if isinstance(projections, str):
32
32
  projections = projections.split(",")
33
33
 
34
- # any project that exists add a # infront of it
34
+ # any projection that exists add a # infront of it
35
35
  projections = ["#" + p if self.is_reserved_word(p) else p for p in projections]
36
36
  return projections
37
37
 
@@ -0,0 +1 @@
1
+ __version__ = '0.1.14'
@@ -155,6 +155,8 @@ class DynamoDBModelUnitTest(unittest.TestCase):
155
155
  self.assertEqual(keys[2].partition_key.value, "users#")
156
156
  self.assertEqual(keys[2].sort_key.attribute_name, "gsi1_sk")
157
157
  self.assertEqual(keys[2].sort_key.value, "lastname#")
158
+ expression = user.helpers.get_filter_expressions(keys[2].key())
159
+ print(f"expression: {expression}")
158
160
 
159
161
  self.assertEqual(keys[3].partition_key.attribute_name, "gsi2_pk")
160
162
  self.assertEqual(keys[3].partition_key.value, "users#")
@@ -195,3 +197,35 @@ class DynamoDBModelUnitTest(unittest.TestCase):
195
197
  self.assertEqual(dictionary.get("gsi2_sk"), "firstname#John#lastname#Smith")
196
198
 
197
199
  print("stop")
200
+
201
+ def test_key_dictionary_key_gen(self):
202
+ """Test Listing Keys"""
203
+ # Arrange
204
+ data = {
205
+ "id": "123456",
206
+ "first_name": "John",
207
+ "age": 30,
208
+ "email": "john@example.com",
209
+ }
210
+
211
+ # Act
212
+ user: User = User().map(data)
213
+ keys: List[DynamoDBKey] = user.list_keys()
214
+
215
+ self.assertEqual(len(keys), 4)
216
+
217
+ dictionary = user.helpers.keys_to_dictionary(keys=keys)
218
+
219
+ self.assertEqual(dictionary.get("pk"), "user#123456")
220
+ self.assertEqual(dictionary.get("sk"), "user#123456")
221
+
222
+ self.assertEqual(dictionary.get("gsi0_pk"), "users#")
223
+ self.assertEqual(dictionary.get("gsi0_sk"), "email#john@example.com")
224
+
225
+ self.assertEqual(dictionary.get("gsi1_pk"), "users#")
226
+ self.assertEqual(dictionary.get("gsi1_sk"), "lastname#")
227
+
228
+ self.assertEqual(dictionary.get("gsi2_pk"), "users#")
229
+ self.assertEqual(dictionary.get("gsi2_sk"), "firstname#John#lastname#")
230
+
231
+ print("stop")
@@ -82,6 +82,7 @@ class DynamoDBModeProjectionlUnitTest(unittest.TestCase):
82
82
  self.assertIsNone(attribute_names)
83
83
 
84
84
  def test_user_model_and_nulls(self):
85
+ """Test nulls"""
85
86
  model: User = User()
86
87
  model.first_name = "John"
87
88
 
@@ -91,6 +92,7 @@ class DynamoDBModeProjectionlUnitTest(unittest.TestCase):
91
92
  self.assertIn("id", expressions)
92
93
 
93
94
  def test_user_limited_projections(self):
95
+ """Test limited projections"""
94
96
  model: User = User()
95
97
  model.first_name = "John"
96
98
 
@@ -107,3 +109,23 @@ class DynamoDBModeProjectionlUnitTest(unittest.TestCase):
107
109
  self.assertNotIn("email", expressions)
108
110
  self.assertNotIn("status", expressions)
109
111
  self.assertIsNone(attributes)
112
+
113
+ def test_user_limited_reserved_projections(self):
114
+ """Test reserved word addition."""
115
+ model: User = User()
116
+ model.first_name = "John"
117
+
118
+ model.projection_expression = "id,status"
119
+ # model.projection_expression_attribute_names = None
120
+ model.auto_generate_projections = False
121
+ expressions = model.projection_expression
122
+ attributes = model.projection_expression_attribute_names
123
+ self.assertIsInstance(expressions, str)
124
+
125
+ self.assertIn("id", expressions)
126
+ self.assertNotIn("first_name", expressions)
127
+ self.assertNotIn("age", expressions)
128
+ self.assertNotIn("email", expressions)
129
+ self.assertIn("#status", expressions)
130
+ # self.assertIsNone(attributes)
131
+ self.assertIn("#status", attributes)
@@ -0,0 +1,51 @@
1
+ """
2
+ Geek Cafe, LLC
3
+ Maintainers: Eric Wilson
4
+ MIT License. See Project Root for the license information.
5
+ """
6
+
7
+ import unittest
8
+ from typing import List, Dict
9
+
10
+
11
+ from tests.dynamodb.models.user_model import User
12
+
13
+
14
+ class DynamoDBModelSerializationUnitTest(unittest.TestCase):
15
+ "Serialization Tests"
16
+
17
+ def test_basic_serialization(self):
18
+ """Test Basic Serlization"""
19
+ # Arrange
20
+ data = {
21
+ "id": "123456",
22
+ "first_name": "John",
23
+ "age": 30,
24
+ "email": "john@example.com",
25
+ }
26
+
27
+ # Act
28
+ serialized_data: User = User().map(data)
29
+
30
+ # Assert
31
+
32
+ self.assertEqual(serialized_data.first_name, "John")
33
+ self.assertEqual(serialized_data.age, 30)
34
+ self.assertEqual(serialized_data.email, "john@example.com")
35
+ self.assertIsInstance(serialized_data, User)
36
+
37
+ key = serialized_data.indexes.primary.key()
38
+ self.assertIsInstance(key, dict)
39
+
40
+ dictionary = serialized_data.to_resource_dictionary()
41
+ self.assertIsInstance(dictionary, dict)
42
+ keys = dictionary.keys()
43
+ self.assertIn("first_name", keys)
44
+ self.assertIn("age", keys)
45
+ self.assertIn("email", keys)
46
+ self.assertIn("id", keys)
47
+ self.assertNotIn("T", keys)
48
+
49
+ user: User = User()
50
+ dictionary = user.to_resource_dictionary()
51
+ self.assertIsInstance(dictionary, dict)
@@ -4,11 +4,11 @@ Maintainers: Eric Wilson
4
4
  MIT License. See Project Root for the license information.
5
5
  """
6
6
 
7
- from typing import Optional, List, Dict
7
+ from typing import Optional
8
8
 
9
- from src.boto3_assist.dynamodb.dynamodb_model_base import DynamoDBModelBase
9
+ from boto3_assist.dynamodb.dynamodb_model_base import DynamoDBModelBase
10
10
  from boto3_assist.dynamodb.dynamodb_index import DynamoDBIndex
11
- from src.boto3_assist.dynamodb.dynamodb_key import DynamoDBKey
11
+ from boto3_assist.dynamodb.dynamodb_key import DynamoDBKey
12
12
 
13
13
 
14
14
  class User(DynamoDBModelBase):
@@ -18,7 +18,7 @@ class User(DynamoDBModelBase):
18
18
  self,
19
19
  id: Optional[str] = None, # pylint: disable=redefined-builtin
20
20
  ):
21
- DynamoDBModelBase.__init__(self)
21
+ super().__init__(self)
22
22
  self.id: Optional[str] = id
23
23
  self.first_name: Optional[str] = None
24
24
  self.last_name: Optional[str] = None
@@ -1 +0,0 @@
1
- __version__ = '0.1.13'
File without changes
File without changes
File without changes
File without changes
File without changes