boto3-assist 0.9.4__tar.gz → 0.10.0__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 (130) hide show
  1. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/PKG-INFO +17 -1
  2. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/README.md +16 -0
  3. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/pyproject.toml +5 -1
  4. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/requirements-dev.txt +1 -1
  5. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/aws_lambda/mock_context.py +2 -1
  6. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/boto3session.py +3 -0
  7. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/cognito/cognito_utility.py +1 -1
  8. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/dynamodb/dynamodb.py +5 -5
  9. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/dynamodb/dynamodb_helpers.py +4 -5
  10. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/s3/s3_object.py +1 -6
  11. boto3_assist-0.10.0/src/boto3_assist/ssm/connection.py +57 -0
  12. boto3_assist-0.10.0/src/boto3_assist/ssm/parameter_store/parameter_store.py +116 -0
  13. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/utilities/datetime_utility.py +9 -3
  14. boto3_assist-0.9.4/src/boto3_assist/utilities/dictionaroy_utility.py → boto3_assist-0.10.0/src/boto3_assist/utilities/dictionary_utility.py +6 -0
  15. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/utilities/file_operations.py +26 -6
  16. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/utilities/http_utility.py +6 -0
  17. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/utilities/numbers_utility.py +6 -0
  18. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/utilities/serialization_utility.py +114 -2
  19. boto3_assist-0.10.0/src/boto3_assist/version.py +1 -0
  20. boto3_assist-0.10.0/tests/parameter_store/parameter_store_test.py +35 -0
  21. boto3_assist-0.10.0/tests/utilities/__init__.py +0 -0
  22. boto3_assist-0.9.4/src/boto3_assist/version.py +0 -1
  23. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/.env.docker +0 -0
  24. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/.env.docker.001 +0 -0
  25. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/.env.docker.nosql.workbench +0 -0
  26. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/.env.unittest +0 -0
  27. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/.gitignore +0 -0
  28. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/.vscode/launch.json +0 -0
  29. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/.vscode/settings.json +0 -0
  30. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/.vscode/tasks.json +0 -0
  31. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/LICENSE-EXPLAINED.txt +0 -0
  32. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/LICENSE.txt +0 -0
  33. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/aws_regions_with_status.csv +0 -0
  34. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/aws_regions_with_status.json +0 -0
  35. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/devops/build.py +0 -0
  36. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/devops/readme.md +0 -0
  37. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/examples/__init__.py +0 -0
  38. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/examples/cloudwatch/log_report.py +0 -0
  39. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/examples/dynamodb/models/order_item_model.py +0 -0
  40. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/examples/dynamodb/models/order_model.py +0 -0
  41. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/examples/dynamodb/models/product_model.py +0 -0
  42. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/examples/dynamodb/models/user_model.py +0 -0
  43. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/examples/dynamodb/models/user_post_model.py +0 -0
  44. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/examples/dynamodb/order_example/main.py +0 -0
  45. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/examples/dynamodb/order_example/products.json +0 -0
  46. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/examples/dynamodb/services/order_item_service.py +0 -0
  47. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/examples/dynamodb/services/order_service.py +0 -0
  48. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/examples/dynamodb/services/product_service.py +0 -0
  49. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/examples/dynamodb/services/table_service.py +0 -0
  50. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/examples/dynamodb/services/user_post_service.py +0 -0
  51. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/examples/dynamodb/services/user_service.py +0 -0
  52. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/examples/dynamodb/services/user_service_client_example.py +0 -0
  53. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/examples/dynamodb/services/user_service_resource_example.py +0 -0
  54. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/examples/dynamodb/user_post_example/main.py +0 -0
  55. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/examples/ec2/regions_report.py +0 -0
  56. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/module-headers.txt +0 -0
  57. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/mypy.ini +0 -0
  58. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/requirements.txt +0 -0
  59. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/run-checks.sh +0 -0
  60. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/run_unit_tests.sh +0 -0
  61. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/__init__.py +0 -0
  62. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/aws_lambda/event_info.py +0 -0
  63. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/cloudwatch/cloudwatch_connection.py +0 -0
  64. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/cloudwatch/cloudwatch_connection_tracker.py +0 -0
  65. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/cloudwatch/cloudwatch_log_connection.py +0 -0
  66. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/cloudwatch/cloudwatch_logs.py +0 -0
  67. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/cloudwatch/cloudwatch_query.py +0 -0
  68. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/cognito/cognito_authorizer.py +0 -0
  69. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/cognito/cognito_connection.py +0 -0
  70. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/cognito/jwks_cache.py +0 -0
  71. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/cognito/user.py +0 -0
  72. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/connection.py +0 -0
  73. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/connection_tracker.py +0 -0
  74. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/dynamodb/dynamodb_connection.py +0 -0
  75. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/dynamodb/dynamodb_importer.py +0 -0
  76. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/dynamodb/dynamodb_index.py +0 -0
  77. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/dynamodb/dynamodb_iservice.py +0 -0
  78. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/dynamodb/dynamodb_key.py +0 -0
  79. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/dynamodb/dynamodb_model_base.py +0 -0
  80. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/dynamodb/dynamodb_model_base_interfaces.py +0 -0
  81. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/dynamodb/dynamodb_reindexer.py +0 -0
  82. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/dynamodb/dynamodb_reserved_words.py +0 -0
  83. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/dynamodb/dynamodb_reserved_words.txt +0 -0
  84. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/dynamodb/readme.md +0 -0
  85. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/dynamodb/troubleshooting.md +0 -0
  86. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/ec2/ec2_connection.py +0 -0
  87. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/environment_services/__init__.py +0 -0
  88. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/environment_services/environment_loader.py +0 -0
  89. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/environment_services/environment_variables.py +0 -0
  90. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/errors/custom_exceptions.py +0 -0
  91. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/http_status_codes.py +0 -0
  92. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/models/serializable_model.py +0 -0
  93. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/s3/s3.py +0 -0
  94. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/s3/s3_bucket.py +0 -0
  95. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/s3/s3_connection.py +0 -0
  96. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/s3/s3_event_data.py +0 -0
  97. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/securityhub/securityhub.py +0 -0
  98. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/securityhub/securityhub_connection.py +0 -0
  99. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/utilities/logging_utility.py +0 -0
  100. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/src/boto3_assist/utilities/string_utility.py +0 -0
  101. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/tests/__init__.py +0 -0
  102. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/tests/__top/__init__.py +0 -0
  103. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/tests/dynamodb/__init__.py +0 -0
  104. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/tests/dynamodb/dbmodels/cms/base.py +0 -0
  105. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/tests/dynamodb/dbmodels/cms/content_block.py +0 -0
  106. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/tests/dynamodb/dbmodels/cms/page.py +0 -0
  107. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/tests/dynamodb/dbmodels/cms/template.py +0 -0
  108. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/tests/dynamodb/dbmodels/simple_model.py +0 -0
  109. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/tests/dynamodb/dbmodels/user_model.py +0 -0
  110. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/tests/dynamodb/dbmodels/user_required_fields_model.py +0 -0
  111. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/tests/dynamodb/dynamodb_model_base_test.py +0 -0
  112. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/tests/dynamodb/dynamodb_model_projections_test.py +0 -0
  113. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/tests/dynamodb/dynamodb_model_serializtion_test.py +0 -0
  114. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/tests/dynamodb/dynamodb_moto_sorting_test.py +0 -0
  115. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/tests/dynamodb/dynamodb_reindex_test.py +0 -0
  116. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/tests/examples_test/__init__.py +0 -0
  117. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/tests/examples_test/user_service_test.py +0 -0
  118. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/tests/lambda/__init__.py +0 -0
  119. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/tests/lambda/event_info_test.py +0 -0
  120. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/tests/models/__init__.py +0 -0
  121. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/tests/models/serializable_model_test.py +0 -0
  122. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/tests/models/serializable_model_wide_test.py +0 -0
  123. {boto3_assist-0.9.4/tests/s3 → boto3_assist-0.10.0/tests/parameter_store}/__init__.py +0 -0
  124. {boto3_assist-0.9.4/tests/utilities → boto3_assist-0.10.0/tests/s3}/__init__.py +0 -0
  125. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/tests/s3/files/test.txt +0 -0
  126. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/tests/s3/s3_event_data_test.py +0 -0
  127. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/tests/s3/s3_file_delete_test.py +0 -0
  128. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/tests/s3/s3_file_upload_test.py +0 -0
  129. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/tests/utilities/serialization_utility_test.py +0 -0
  130. {boto3_assist-0.9.4 → boto3_assist-0.10.0}/tests/utilities/string_utility_test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boto3_assist
3
- Version: 0.9.4
3
+ Version: 0.10.0
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
@@ -51,3 +51,19 @@ pip install boto3-assist
51
51
 
52
52
  ```
53
53
 
54
+ ## Running Unit Tests
55
+ Several of our tests use a mocking library to simulate connections to S3, DynamoDB, etc. In order to use those tests, you will need to have a `.env.unittest` file at the root of this project (which our tests will attempt to locate and load).
56
+
57
+ For your convenince the `.evn.unittest` file has been added to this project. The values should not point to live AWS profiles, instead it should use the values added.
58
+
59
+ Since we also point to a profile, you should create the profile in the `~/.aws/config` file. The entry should look like the following:
60
+
61
+ ```toml
62
+ [profile moto-mock-tests]
63
+ region = us-east-1
64
+ output = json
65
+ aws_access_key_id = test
66
+ aws_secret_access_key = test
67
+
68
+ ```
69
+
@@ -28,3 +28,19 @@ pip install boto3-assist
28
28
 
29
29
  ```
30
30
 
31
+ ## Running Unit Tests
32
+ Several of our tests use a mocking library to simulate connections to S3, DynamoDB, etc. In order to use those tests, you will need to have a `.env.unittest` file at the root of this project (which our tests will attempt to locate and load).
33
+
34
+ For your convenince the `.evn.unittest` file has been added to this project. The values should not point to live AWS profiles, instead it should use the values added.
35
+
36
+ Since we also point to a profile, you should create the profile in the `~/.aws/config` file. The entry should look like the following:
37
+
38
+ ```toml
39
+ [profile moto-mock-tests]
40
+ region = us-east-1
41
+ output = json
42
+ aws_access_key_id = test
43
+ aws_secret_access_key = test
44
+
45
+ ```
46
+
@@ -5,9 +5,13 @@ build-backend = "hatchling.build"
5
5
  [tool.hatch.build.targets.wheel]
6
6
  packages = ["src/boto3_assist"]
7
7
 
8
+ [tool.pytest.ini_options]
9
+ pythonpath = ["src"]
10
+ testpaths = ["tests"]
11
+
8
12
  [project]
9
13
  name = "boto3_assist"
10
- version = "0.9.4"
14
+ version = "0.10.0"
11
15
 
12
16
  authors = [
13
17
  { name="Eric Wilson", email="boto3-assist@geekcafe.com" }
@@ -8,7 +8,7 @@ mypy_boto3_cloudwatch
8
8
  mypy_boto3_s3
9
9
  mypy_boto3_cognito_idp
10
10
  mypy_boto3_securityhub
11
-
11
+ mypy_boto3_ssm
12
12
  moto [dynamodb2] # mocks for unit tests
13
13
  # setuptools
14
14
  types-python-dateutil
@@ -1,4 +1,5 @@
1
1
  from aws_lambda_powertools.utilities.typing import LambdaContext
2
2
 
3
3
 
4
- class MockLambdaContext(LambdaContext)
4
+ class MockLambdaContext(LambdaContext):
5
+ pass
@@ -63,6 +63,9 @@ class Boto3SessionManager:
63
63
  logger.debug("Connecting without assuming a role.")
64
64
  self.__session = self.__get_aws_session(profile, region)
65
65
 
66
+ if profile:
67
+ print(f"Connecting with a profile: {profile}")
68
+
66
69
  def __assume_role(self):
67
70
  """Assume an AWS IAM role."""
68
71
  try:
@@ -12,7 +12,7 @@ from aws_lambda_powertools import Logger
12
12
 
13
13
  from boto3_assist.cognito.user import CognitoUser
14
14
  from boto3_assist.utilities.string_utility import StringUtility
15
- from boto3_assist.utilities.dictionaroy_utility import DictionaryUtilitiy
15
+ from boto3_assist.utilities.dictionary_utility import DictionaryUtilitiy
16
16
  from boto3_assist.cognito.cognito_connection import CognitoConnection
17
17
 
18
18
  logger = Logger()
@@ -7,7 +7,7 @@ MIT License. See Project Root for the license information.
7
7
  import os
8
8
  from typing import List, Optional, overload, Dict, Any
9
9
 
10
- from aws_lambda_powertools import Tracer, Logger
10
+ from aws_lambda_powertools import Logger
11
11
  from boto3.dynamodb.conditions import (
12
12
  Key,
13
13
  # And,
@@ -22,7 +22,7 @@ from boto3_assist.utilities.string_utility import StringUtility
22
22
 
23
23
 
24
24
  logger = Logger()
25
- tracer = Tracer()
25
+
26
26
 
27
27
 
28
28
  class DynamoDB(DynamoDBConnection):
@@ -55,7 +55,7 @@ class DynamoDB(DynamoDBConnection):
55
55
  )
56
56
  logger.setLevel(os.getenv("LOG_LEVEL", "INFO"))
57
57
 
58
- @tracer.capture_method
58
+
59
59
  def save(
60
60
  self,
61
61
  item: dict | DynamoDBModelBase,
@@ -169,7 +169,7 @@ class DynamoDB(DynamoDBConnection):
169
169
  call_type: str = "resource",
170
170
  ) -> Dict[str, Any]: ...
171
171
 
172
- @tracer.capture_method
172
+
173
173
  def get(
174
174
  self,
175
175
  key: Optional[dict] = None,
@@ -344,7 +344,7 @@ class DynamoDB(DynamoDBConnection):
344
344
  ) -> dict:
345
345
  pass
346
346
 
347
- @tracer.capture_method
347
+
348
348
  def delete(
349
349
  self,
350
350
  *,
@@ -7,11 +7,11 @@ MIT License. See Project Root for the license information.
7
7
  from typing import List, Any, Dict
8
8
 
9
9
  from boto3.dynamodb.conditions import ConditionBase, Key, And, Equals
10
- from aws_lambda_powertools import Tracer, Logger
10
+ from aws_lambda_powertools import Logger
11
11
  from boto3_assist.dynamodb.dynamodb_index import DynamoDBIndex
12
12
 
13
13
  logger = Logger()
14
- tracer = Tracer()
14
+
15
15
 
16
16
 
17
17
  class DynamoDBHelpers:
@@ -118,7 +118,7 @@ class DynamoDBHelpers:
118
118
  logger.error({"exception": str(e)})
119
119
  return "unknown"
120
120
 
121
- @tracer.capture_method(capture_response=False)
121
+
122
122
  def wrap_response(self, items, dynamodb_response: dict, diagnostics) -> dict:
123
123
  """A wrapper for response data"""
124
124
  last_key = dynamodb_response.get("LastEvaluatedKey", None)
@@ -135,8 +135,7 @@ class DynamoDBHelpers:
135
135
  }
136
136
 
137
137
  return response
138
-
139
- @tracer.capture_method(capture_response=False)
138
+
140
139
  def wrap_collection_response(self, collection: List[dict]) -> dict[str, List]:
141
140
  """
142
141
  Wraps Up Some usefull information when dealing with
@@ -593,12 +593,7 @@ class S3Object:
593
593
  If running in AWS Lambda, returns '/tmp'.
594
594
  Otherwise, returns the system's standard temp directory.
595
595
  """
596
- if "AWS_LAMBDA_FUNCTION_NAME" in os.environ:
597
- # In AWS Lambda environment
598
- return "/tmp"
599
- else:
600
- # Not in AWS Lambda, use the system's default temp directory
601
- return tempfile.gettempdir()
596
+ return FileOperations.get_tmp_directory()
602
597
 
603
598
  def encode(
604
599
  self, text: str, encoding: str = "utf-8", errors: str = "strict"
@@ -0,0 +1,57 @@
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
+
12
+ from boto3_assist.connection import Connection
13
+
14
+ if TYPE_CHECKING:
15
+ from mypy_boto3_ssm import Client
16
+ else:
17
+ Client = object
18
+
19
+
20
+ logger = Logger()
21
+
22
+
23
+ class SSMConnection(Connection):
24
+ """Connection"""
25
+
26
+ def __init__(
27
+ self,
28
+ *,
29
+ aws_profile: Optional[str] = None,
30
+ aws_region: Optional[str] = None,
31
+ aws_end_point_url: Optional[str] = None,
32
+ aws_access_key_id: Optional[str] = None,
33
+ aws_secret_access_key: Optional[str] = None,
34
+ ) -> None:
35
+ super().__init__(
36
+ service_name="ssm",
37
+ aws_profile=aws_profile,
38
+ aws_region=aws_region,
39
+ aws_access_key_id=aws_access_key_id,
40
+ aws_secret_access_key=aws_secret_access_key,
41
+ aws_end_point_url=aws_end_point_url,
42
+ )
43
+
44
+ self.__client: Client | None = None
45
+
46
+ @property
47
+ def client(self) -> Client:
48
+ """Client Connection"""
49
+ if self.__client is None:
50
+ self.__client = self.session.client
51
+
52
+ return self.__client
53
+
54
+ @client.setter
55
+ def client(self, value: Client):
56
+ logger.info("Setting Client")
57
+ self.__client = value
@@ -0,0 +1,116 @@
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, Literal
8
+
9
+ from botocore.exceptions import ClientError
10
+ from boto3_assist.ssm.connection import SSMConnection
11
+
12
+
13
+ class ParameterStore(SSMConnection):
14
+ """Parameter Store"""
15
+
16
+ def get_parameter(self, name: str, with_decryption=True):
17
+ """
18
+ Retrieve a parameter from Parameter Store.
19
+
20
+ :param name: The full name of the parameter.
21
+ :param with_decryption: If True, decrypt secure strings.
22
+ :return: The parameter value or None if an error occurs.
23
+ """
24
+ try:
25
+ response = self.client.get_parameter(
26
+ Name=name, WithDecryption=with_decryption
27
+ )
28
+ return response["Parameter"]["Value"]
29
+ except ClientError as e:
30
+ print(f"Error getting parameter {name}: {e}")
31
+ raise
32
+
33
+ def put_parameter(
34
+ self,
35
+ name: str,
36
+ value: str,
37
+ type: Literal["String", "StringList", "SecureString"] = "String", # pylint: disable=redefined-builtin
38
+ overwrite=True,
39
+ ):
40
+ """
41
+ Create or update a parameter in Parameter Store.
42
+
43
+ :param name: The full name of the parameter.
44
+ :param value: The value to store.
45
+ :param type: Parameter type ('String', 'StringList', or 'SecureString').
46
+ :param overwrite: If True, overwrite an existing parameter.
47
+ :return: The response from the put_parameter call or None on error.
48
+ """
49
+ try:
50
+ response = self.client.put_parameter(
51
+ Name=name, Value=value, Type=type, Overwrite=overwrite
52
+ )
53
+ return response
54
+ except ClientError as e:
55
+ print(f"Error putting parameter {name}: {e}")
56
+ raise
57
+
58
+ def delete_parameter(self, name: str):
59
+ """
60
+ Delete a parameter from Parameter Store.
61
+
62
+ :param name: The full name of the parameter.
63
+ :return: The response from the delete_parameter call or None on error.
64
+ """
65
+ try:
66
+ response = self.client.delete_parameter(Name=name)
67
+ return response
68
+ except ClientError as e:
69
+ print(f"Error deleting parameter {name}: {e}")
70
+ raise
71
+
72
+ def list_parameters(self, path: str = "/", recursive=True):
73
+ """
74
+ List parameters in a given path.
75
+
76
+ :param path: The hierarchical path for the parameters.
77
+ :param recursive: If True, retrieve parameters recursively.
78
+ :return: A list of parameter metadata dictionaries.
79
+ """
80
+ try:
81
+ paginator = self.client.get_paginator("describe_parameters")
82
+ parameters = []
83
+ filters = [
84
+ {
85
+ "Key": "Path",
86
+ "Option": "Recursive" if recursive else "OneLevel",
87
+ "Values": [path],
88
+ }
89
+ ]
90
+ for page in paginator.paginate(ParameterFilters=filters):
91
+ parameters.extend(page.get("Parameters", []))
92
+ return parameters
93
+ except ClientError as e:
94
+ print(f"Error listing parameters for path {path}: {e}")
95
+ raise
96
+
97
+
98
+ # Example usage:
99
+ if __name__ == "__main__":
100
+ # Initialize the ParameterStore class.
101
+ ssm = ParameterStore()
102
+ # Example: Put a parameter.
103
+ put_response = ssm.put_parameter("/myapp/AccountNumber", "123456789012")
104
+ print("Put parameter response:", put_response)
105
+
106
+ # Example: Get a parameter.
107
+ account_number = ssm.get_parameter("/myapp/AccountNumber")
108
+ print("Account Number:", account_number)
109
+
110
+ # Example: List parameters under /myapp.
111
+ params = ssm.list_parameters(path="/myapp")
112
+ print("Parameters under /myapp:", params)
113
+
114
+ # Example: Delete a parameter.
115
+ delete_response = ssm.delete_parameter("/myapp/AccountNumber")
116
+ print("Delete parameter response:", delete_response)
@@ -1,12 +1,18 @@
1
+ """
2
+ Geek Cafe, LLC
3
+ Maintainers: Eric Wilson
4
+ MIT License. See Project Root for the license information.
5
+ """
6
+
1
7
  import uuid
2
8
  from datetime import UTC, datetime, timedelta, timezone
3
9
  from typing import Any
4
10
  import pytz # type: ignore
5
- from aws_lambda_powertools import Tracer, Logger
11
+ from aws_lambda_powertools import Logger
6
12
  from dateutil.relativedelta import relativedelta
7
13
 
8
14
 
9
- tracer = Tracer()
15
+
10
16
  logger = Logger()
11
17
 
12
18
  _last_timestamp = None
@@ -41,7 +47,7 @@ class DatetimeUtility:
41
47
  return datetime.now(timezone.utc)
42
48
 
43
49
  @staticmethod
44
- @tracer.capture_method(capture_response=False)
50
+
45
51
  def string_to_date(string_date: str | datetime) -> datetime | None:
46
52
  """
47
53
  Description: takes a string value and returns it as a datetime.
@@ -1,3 +1,9 @@
1
+ """
2
+ Geek Cafe, LLC
3
+ Maintainers: Eric Wilson
4
+ MIT License. See Project Root for the license information.
5
+ """
6
+
1
7
  from typing import List
2
8
 
3
9
 
@@ -1,13 +1,16 @@
1
+ """
2
+ Geek Cafe, LLC
3
+ Maintainers: Eric Wilson
4
+ MIT License. See Project Root for the license information.
5
+ """
6
+
1
7
  import os
8
+
2
9
  import shutil
3
- import json
4
- import zipfile
5
- from typing import List, Any, Dict
6
- from pathlib import Path
7
- import re
10
+ import tempfile
8
11
 
9
- from aws_lambda_powertools import Logger
10
12
 
13
+ from aws_lambda_powertools import Logger
11
14
 
12
15
  logger = Logger()
13
16
 
@@ -113,3 +116,20 @@ class FileOperations:
113
116
  logger.debug(f"extension after prefix removal: {extention}")
114
117
 
115
118
  return extention
119
+
120
+ @staticmethod
121
+ def get_tmp_directory() -> str:
122
+ """
123
+ Get the temp directory
124
+ """
125
+ # are we in an aws lambda function?
126
+ if os.environ.get("AWS_LAMBDA_FUNCTION_NAME"):
127
+ # we are in a lambda function /tmp is the only place
128
+ # we can write to
129
+ if not os.path.exists("/tmp"):
130
+ raise ValueError("Temp directory does not exist.")
131
+
132
+ tmp_dir = "/tmp"
133
+ return tmp_dir
134
+
135
+ return tempfile.gettempdir()
@@ -1,3 +1,9 @@
1
+ """
2
+ Geek Cafe, LLC
3
+ Maintainers: Eric Wilson
4
+ MIT License. See Project Root for the license information.
5
+ """
6
+
1
7
  from urllib.parse import unquote
2
8
  from typing import Dict, Any
3
9
 
@@ -1,3 +1,9 @@
1
+ """
2
+ Geek Cafe, LLC
3
+ Maintainers: Eric Wilson
4
+ MIT License. See Project Root for the license information.
5
+ """
6
+
1
7
  import math
2
8
  from typing import List, Optional
3
9
  from aws_lambda_powertools import Logger
@@ -1,4 +1,8 @@
1
- """Serialization Utility"""
1
+ """
2
+ Geek Cafe, LLC
3
+ Maintainers: Eric Wilson
4
+ MIT License. See Project Root for the license information.
5
+ """
2
6
 
3
7
  import datetime as dt
4
8
  import decimal
@@ -8,7 +12,7 @@ import uuid
8
12
  from datetime import datetime
9
13
  from decimal import Decimal
10
14
  from typing import Any, Dict, List, TypeVar
11
-
15
+ import re
12
16
  from aws_lambda_powertools import Logger
13
17
 
14
18
  T = TypeVar("T")
@@ -99,6 +103,114 @@ class JsonEncoder(json.JSONEncoder):
99
103
  ) # Or any other way you wish to serialize objects without __dict__
100
104
 
101
105
 
106
+ class JsonConversions:
107
+ """
108
+ Json Conversion Utility
109
+ Used for snake_case to camelCase and vice versa
110
+ """
111
+
112
+ @staticmethod
113
+ def _camel_to_snake(value: str) -> str:
114
+ """Converts a camelCase to a snake_case"""
115
+ # Insert underscores before uppercase letters, then convert to lowercase.
116
+ s1 = re.sub(r"(.)([A-Z][a-z]+)", r"\1_\2", value)
117
+ return re.sub(r"([a-z0-9])([A-Z])", r"\1_\2", s1).lower()
118
+
119
+ @staticmethod
120
+ def _snake_to_camel(value: str) -> str:
121
+ """Converts a value from snake_case to camelCase"""
122
+ # Split the value by underscores and capitalize each component except the first.
123
+ components = value.split("_")
124
+ return components[0] + "".join(x.title() for x in components[1:])
125
+
126
+ @staticmethod
127
+ def _convert_keys(data, convert_func, deep: bool = True):
128
+ """
129
+ Recursively converts dictionary keys using the provided convert_func.
130
+
131
+ Parameters:
132
+ data: The input data (dict, list, or other) to process.
133
+ convert_func: Function to convert the keys (e.g. camel_to_snake or snake_to_camel).
134
+ deep (bool): If True (default), convert keys in all nested dictionaries.
135
+ If False, only convert the keys at the current level.
136
+ """
137
+ if isinstance(data, dict):
138
+ new_dict = {}
139
+ for key, value in data.items():
140
+ new_key = convert_func(key)
141
+ # Only process nested structures if deep is True.
142
+ new_dict[new_key] = (
143
+ JsonConversions._convert_keys(value, convert_func, deep)
144
+ if deep
145
+ else value
146
+ )
147
+ return new_dict
148
+ elif isinstance(data, list):
149
+ # For lists, if deep conversion is enabled, process each element.
150
+ return [
151
+ JsonConversions._convert_keys(item, convert_func, deep)
152
+ if deep
153
+ else item
154
+ for item in data
155
+ ]
156
+ else:
157
+ return data
158
+
159
+ @staticmethod
160
+ def json_camel_to_snake(data, deep: bool = True):
161
+ """Converts all keys in the JSON structure from camelCase to snake_case.
162
+
163
+ Parameters:
164
+ data: The JSON-like structure (dict or list) to process.
165
+ deep (bool): If True, process keys in all nested dictionaries; if False, only at the first level.
166
+ """
167
+ return JsonConversions._convert_keys(
168
+ data, JsonConversions._camel_to_snake, deep
169
+ )
170
+
171
+ @staticmethod
172
+ def json_snake_to_camel(data, deep: bool = True):
173
+ """Converts all keys in the JSON structure from snake_case to camelCase.
174
+
175
+ Parameters:
176
+ data: The JSON-like structure (dict or list) to process.
177
+ deep (bool): If True, process keys in all nested dictionaries; if False, only at the first level.
178
+ """
179
+ return JsonConversions._convert_keys(
180
+ data, JsonConversions._snake_to_camel, deep
181
+ )
182
+
183
+ # # Example usage:
184
+ # if __name__ == "__main__":
185
+ # sample_json = {
186
+ # "firstName": "John",
187
+ # "lastName": "Doe",
188
+ # "address": {"streetAddress": "21 2nd Street", "city": "New York"},
189
+ # "phoneNumbers": [
190
+ # {"phoneType": "home", "phoneNumber": "2125551234"},
191
+ # {"phoneType": "fax", "phoneNumber": "6465554567"},
192
+ # ],
193
+ # }
194
+
195
+ # print("Original JSON:")
196
+ # print(sample_json)
197
+
198
+ # # Convert from camelCase to snake_case on all levels.
199
+ # snake_json_deep = json_camel_to_snake(sample_json, deep=True)
200
+ # print("\nConverted to snake_case (deep conversion):")
201
+ # print(snake_json_deep)
202
+
203
+ # # Convert from camelCase to snake_case only at the first level.
204
+ # snake_json_shallow = json_camel_to_snake(sample_json, deep=False)
205
+ # print("\nConverted to snake_case (first-level only):")
206
+ # print(snake_json_shallow)
207
+
208
+ # # Convert back from snake_case to camelCase on all levels.
209
+ # camel_json_deep = json_snake_to_camel(snake_json_deep, deep=True)
210
+ # print("\nConverted back to camelCase (deep conversion):")
211
+ # print(camel_json_deep)
212
+
213
+
102
214
  class Serialization:
103
215
  """
104
216
  Serialization Class
@@ -0,0 +1 @@
1
+ __version__ = '0.10.0'
@@ -0,0 +1,35 @@
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
+
9
+ import moto
10
+
11
+ from boto3_assist.environment_services.environment_loader import EnvironmentLoader
12
+ from boto3_assist.ssm.parameter_store.parameter_store import ParameterStore
13
+
14
+
15
+ @moto.mock_aws
16
+ class ParameterStoreTest(unittest.TestCase):
17
+ """Parameter store tests - with mocking"""
18
+
19
+ def setUp(self):
20
+ """Setup"""
21
+ ev: EnvironmentLoader = EnvironmentLoader()
22
+ # NOTE: you need to make sure the the env file below exists or you will get an error
23
+ # this also requires the @moto.mock_aws decorator
24
+ ev.load_environment_file(file_name=".env.unittest")
25
+ # ev.load_environment_file(file_name=".env")
26
+
27
+ def test_get_parameter(self):
28
+ parameter_store = ParameterStore()
29
+ parameter_name = "/dev/test"
30
+ parameter_value = "test_1"
31
+
32
+ parameter_store.put_parameter(parameter_name, parameter_value)
33
+ response = parameter_store.get_parameter(parameter_name)
34
+
35
+ self.assertEqual(response, parameter_value)
File without changes
@@ -1 +0,0 @@
1
- __version__ = '0.9.4'
File without changes
File without changes
File without changes
File without changes