clear-skies-aws 1.9.18__py3-none-any.whl → 1.10.1__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.
- {clear_skies_aws-1.9.18.dist-info → clear_skies_aws-1.10.1.dist-info}/METADATA +5 -1
- {clear_skies_aws-1.9.18.dist-info → clear_skies_aws-1.10.1.dist-info}/RECORD +17 -13
- clearskies_aws/actions/assume_role_test.py +5 -2
- clearskies_aws/backends/__init__.py +10 -0
- clearskies_aws/backends/dynamo_db_backend.py +10 -7
- clearskies_aws/backends/dynamo_db_backend_test.py +71 -65
- clearskies_aws/backends/dynamo_db_condition_parser.py +365 -0
- clearskies_aws/backends/dynamo_db_condition_parser_test.py +266 -0
- clearskies_aws/backends/dynamo_db_parti_ql_backend.py +1123 -0
- clearskies_aws/backends/dynamo_db_parti_ql_backend_test.py +544 -0
- clearskies_aws/contexts/lambda_sqs_standard_partial_batch_test.py +11 -16
- clearskies_aws/di/standard_dependencies.py +47 -5
- clearskies_aws/input_outputs/lambda_api_gateway_test.py +27 -19
- clearskies_aws/secrets/parameter_store_test.py +5 -2
- clearskies_aws/secrets/secrets_manager_test.py +5 -2
- {clear_skies_aws-1.9.18.dist-info → clear_skies_aws-1.10.1.dist-info}/LICENSE +0 -0
- {clear_skies_aws-1.9.18.dist-info → clear_skies_aws-1.10.1.dist-info}/WHEEL +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: clear-skies-aws
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.10.1
|
|
4
4
|
Summary: clearskies bindings for working in AWS
|
|
5
5
|
License: MIT
|
|
6
6
|
Author: Conor Mancone
|
|
@@ -14,8 +14,12 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.13
|
|
15
15
|
Provides-Extra: akeyless
|
|
16
16
|
Provides-Extra: ses
|
|
17
|
+
Requires-Dist: akeyless (>=4.0.0,<5.0.0) ; extra == "akeyless"
|
|
18
|
+
Requires-Dist: akeyless-cloud-id (>=0.2.3,<0.3.0) ; extra == "akeyless"
|
|
17
19
|
Requires-Dist: boto3 (>=1.26.148,<2.0.0)
|
|
18
20
|
Requires-Dist: clear-skies (>=1.14.4,<2.0.0)
|
|
21
|
+
Requires-Dist: jinja2 (>=3.1.2,<4.0.0) ; extra == "ses"
|
|
22
|
+
Requires-Dist: types-boto3[dynamodb,sns,sqs] (>=1.38.13,<2.0.0)
|
|
19
23
|
Project-URL: Repository, https://github.com/cmancone/clearskies-aws
|
|
20
24
|
Description-Content-Type: text/markdown
|
|
21
25
|
|
|
@@ -2,7 +2,7 @@ clearskies_aws/__init__.py,sha256=BZKL4SIyxx4MXpyP5hmwsMo2oJatyv5c2wjJOPzKBQ4,13
|
|
|
2
2
|
clearskies_aws/actions/__init__.py,sha256=w_IWJg4UHV9Opv69zheH7ZHj1BnCzYLlm2JhFvHQCf8,2998
|
|
3
3
|
clearskies_aws/actions/action_aws.py,sha256=zBXsvhBDDm2dAU4MVlub84Ld1YNZ6ey8_zf4OeTe8go,4254
|
|
4
4
|
clearskies_aws/actions/assume_role.py,sha256=tZHKMTQaImj_EAWormFZdIPkR_db7yBwOJxYaUyuGdA,4085
|
|
5
|
-
clearskies_aws/actions/assume_role_test.py,sha256=
|
|
5
|
+
clearskies_aws/actions/assume_role_test.py,sha256=AoXWRtApRZz_oPDj6QhT0ERmYjKOHOXLNet-MgbbeB8,2451
|
|
6
6
|
clearskies_aws/actions/ses.py,sha256=xJ0NEFPP-8kARPGjDv1yf_bhAiaIIM1mDzMxY22GE5E,7925
|
|
7
7
|
clearskies_aws/actions/ses_test.py,sha256=lyNbqI46Ld_ZUKtWLgSwwfSOFksQ39H4hzPS3eTx7nk,3076
|
|
8
8
|
clearskies_aws/actions/sns.py,sha256=00E-eCQuq3Ygscyia928K8jX8rhDZrl5kyasM0st_uI,2288
|
|
@@ -11,9 +11,13 @@ clearskies_aws/actions/sqs.py,sha256=i-QyyFy-ImivXk-m-Bn9Mh5BF5qODthUyZAQVRsb8vs
|
|
|
11
11
|
clearskies_aws/actions/sqs_test.py,sha256=aazVN-bY6E17Pu3hDwLldj6YPirbqXjM6LfYFomUVmQ,4040
|
|
12
12
|
clearskies_aws/actions/step_function.py,sha256=wiDgGdOWdY0zVoClDsX08YFZqTR0bK3ydpyj0Qa7w_s,2599
|
|
13
13
|
clearskies_aws/actions/step_function_test.py,sha256=0gRYLDVRt2R-Cv-5Pr2ui4Gbp8rg9nPhQY4ERALg6qU,3837
|
|
14
|
-
clearskies_aws/backends/__init__.py,sha256=
|
|
15
|
-
clearskies_aws/backends/dynamo_db_backend.py,sha256=
|
|
16
|
-
clearskies_aws/backends/dynamo_db_backend_test.py,sha256=
|
|
14
|
+
clearskies_aws/backends/__init__.py,sha256=t98x6QNF2bvKzVI_owS4L3eG5JNVtsLS9c2fBw8uh9s,379
|
|
15
|
+
clearskies_aws/backends/dynamo_db_backend.py,sha256=i-Na3McQDbyCYmQewBPKgbWEd3A3pf2wfmLs6FsRJ48,29487
|
|
16
|
+
clearskies_aws/backends/dynamo_db_backend_test.py,sha256=wtymsOEVzO9y7_Whu9cCRyioRTmSimbLmRQSt3J4cik,13106
|
|
17
|
+
clearskies_aws/backends/dynamo_db_condition_parser.py,sha256=v-DO4ijdjiHwBsSDF3dUgqQw5twCcG-5NA1aq7kUYQ0,13239
|
|
18
|
+
clearskies_aws/backends/dynamo_db_condition_parser_test.py,sha256=n7snumB8GxyMBVlj-HL7JrsNj-ZJ91c5gdik0UNM5Ag,12664
|
|
19
|
+
clearskies_aws/backends/dynamo_db_parti_ql_backend.py,sha256=pVd_N7XFf9PcTAm6rhMxih_sj9Ix6RkRj3LwmFy_Mr4,48544
|
|
20
|
+
clearskies_aws/backends/dynamo_db_parti_ql_backend_test.py,sha256=7gH-RDh7JeaiEGLXsOB512SLmOp0hjdtWQ1cMmexvDM,23649
|
|
17
21
|
clearskies_aws/backends/sqs_backend.py,sha256=hT1JCvCMU76Q4Ir7OeX8U8eAMLIu1_tMwGgaN9rpsPk,2726
|
|
18
22
|
clearskies_aws/backends/sqs_backend_test.py,sha256=iCuHVVqZIR_PDGUUMZIkpir8yyJy3dcPR00AWR2N25U,1138
|
|
19
23
|
clearskies_aws/contexts/__init__.py,sha256=YjwRaSoAqC-nmo3aFB8rzyuiHSP9mi77FVM-8RF0hRE,472
|
|
@@ -26,17 +30,17 @@ clearskies_aws/contexts/lambda_http_gateway.py,sha256=9gmlTTPkxrtLmOQa7uUojCk9tF
|
|
|
26
30
|
clearskies_aws/contexts/lambda_invocation.py,sha256=U_S3cuY3G1_7ktzGiFTiO2LUnqauqvEDfKKEhYdPtpg,1336
|
|
27
31
|
clearskies_aws/contexts/lambda_sns.py,sha256=crIo3S78N8xfthZsv0l5ooNlpF21ETjoWmHe1WCGQ4w,1364
|
|
28
32
|
clearskies_aws/contexts/lambda_sqs_standard_partial_batch.py,sha256=iypcI4BpxV4IHcKKUWDxK3HuGyaYiP5YPwpFAm4auCw,1801
|
|
29
|
-
clearskies_aws/contexts/lambda_sqs_standard_partial_batch_test.py,sha256=
|
|
33
|
+
clearskies_aws/contexts/lambda_sqs_standard_partial_batch_test.py,sha256=SkEIV_cgxCi-1zC3WXsRNyG6bCt7LB_6CWpxvB8QPxo,1855
|
|
30
34
|
clearskies_aws/contexts/wsgi.py,sha256=wmHnDIfcrQN0I547uE2mlHHQtOLOpLfpbKpBJkw5puY,510
|
|
31
35
|
clearskies_aws/di/__init__.py,sha256=KLq6G-CKR-Vdk9LZe5TijW_U-McJlrp1QuIXqmyAL-A,56
|
|
32
|
-
clearskies_aws/di/standard_dependencies.py,sha256=
|
|
36
|
+
clearskies_aws/di/standard_dependencies.py,sha256=TRST5BxxPQpWJyvXnAwCRJWYRDXC7qM05X3ffYI7EXc,2023
|
|
33
37
|
clearskies_aws/handlers/__init__.py,sha256=E2x04QGy5dfaDIB5Xu8IRWwgypIrgGEZibijtKWe8jM,112
|
|
34
38
|
clearskies_aws/handlers/secrets_manager_rotation.py,sha256=KV4XWKar4gT0Xu0eM_D75ECzYkjXxjeZtkOopPRG9rc,7471
|
|
35
39
|
clearskies_aws/handlers/simple_body_routing.py,sha256=FGdeDY8nZIGfCOn0oOHi6EOP1h4xXcBP3W9fH0NuBlc,1449
|
|
36
40
|
clearskies_aws/input_outputs/__init__.py,sha256=Tf8kWN95nwUbvlVaboYT06ICtSuZd0MPPzwWhO5iQGs,385
|
|
37
41
|
clearskies_aws/input_outputs/cli_websocket_mock.py,sha256=J3PDYnFxOzqYhmlxWFcobbb4McKpsGduIBq6jdSAx5Y,434
|
|
38
42
|
clearskies_aws/input_outputs/lambda_api_gateway.py,sha256=Xi9IdT0u20IMbaIJMBtF2wmsNLCDvmEUVoYB9IRqV00,3479
|
|
39
|
-
clearskies_aws/input_outputs/lambda_api_gateway_test.py,sha256=
|
|
43
|
+
clearskies_aws/input_outputs/lambda_api_gateway_test.py,sha256=B4tUxTqnAEeV0D0VRMu0HyphOJKNij-LtFd2ERcnKI8,2979
|
|
40
44
|
clearskies_aws/input_outputs/lambda_api_gateway_web_socket.py,sha256=kG2fys9X7TailvlOBzIMItuSI8rlvDbBD4AXtI091hM,308
|
|
41
45
|
clearskies_aws/input_outputs/lambda_elb.py,sha256=b675h0DxTGo9YscXN4mwzRGzP3hNSie4iPRKOg3kKPI,750
|
|
42
46
|
clearskies_aws/input_outputs/lambda_http_gateway.py,sha256=YQk7GlQWtQjDiKWhX5jvXc3un1eq2sm1v_jl6iseNoQ,692
|
|
@@ -57,11 +61,11 @@ clearskies_aws/secrets/additional_configs/mysql_connection_dynamic_producer_via_
|
|
|
57
61
|
clearskies_aws/secrets/additional_configs/mysql_connection_dynamic_producer_via_ssm_bastion.py,sha256=Llvg8uQW8J-qndAlDDtg9TY_Tvu2h9tUzchxxUtaRik,6444
|
|
58
62
|
clearskies_aws/secrets/akeyless_with_ssm_cache.py,sha256=4_ep7P2SXei3hNbLrMhUSmr14GTzK69hkzjIYYU-dA4,1443
|
|
59
63
|
clearskies_aws/secrets/parameter_store.py,sha256=lxBlp_9d2-vVjGNfl5859XzZCcLVMMrZtlJG8lKGVPA,1810
|
|
60
|
-
clearskies_aws/secrets/parameter_store_test.py,sha256=
|
|
64
|
+
clearskies_aws/secrets/parameter_store_test.py,sha256=35fTNau4tq_D4elMwyyByIiLesnmn05QhC_X1FVQXsM,763
|
|
61
65
|
clearskies_aws/secrets/secrets_manager.py,sha256=jlpfAFC23EeSpm50L8B-yrXg4IROQq-M_90zzXDp_ak,3056
|
|
62
|
-
clearskies_aws/secrets/secrets_manager_test.py,sha256=
|
|
66
|
+
clearskies_aws/secrets/secrets_manager_test.py,sha256=__YSe-YRbbE1S1SBvZZFQd3brIX5DPX2_wE9MI_Ezx0,788
|
|
63
67
|
clearskies_aws/web_socket_connection_model.py,sha256=d_Au_Pu7YXBfc7_lbuI7zz4MZ8ZOOwGM0oooppEofcI,1776
|
|
64
|
-
clear_skies_aws-1.
|
|
65
|
-
clear_skies_aws-1.
|
|
66
|
-
clear_skies_aws-1.
|
|
67
|
-
clear_skies_aws-1.
|
|
68
|
+
clear_skies_aws-1.10.1.dist-info/LICENSE,sha256=3Ehd0g3YOpCj8sqj0Xjq5qbOtjjgk9qzhhD9YjRQgOA,1053
|
|
69
|
+
clear_skies_aws-1.10.1.dist-info/METADATA,sha256=f3IkhGylUcnIZSITx8j56rD5LJWTEks69c5FTZjGqfI,8784
|
|
70
|
+
clear_skies_aws-1.10.1.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
|
|
71
|
+
clear_skies_aws-1.10.1.dist-info/RECORD,,
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import unittest
|
|
2
2
|
from unittest.mock import MagicMock, call
|
|
3
|
+
|
|
3
4
|
from .assume_role import AssumeRole
|
|
5
|
+
|
|
6
|
+
|
|
4
7
|
class AssumeRoleTest(unittest.TestCase):
|
|
5
8
|
def test_with_external_id(self):
|
|
6
9
|
sts = MagicMock()
|
|
@@ -18,7 +21,7 @@ class AssumeRoleTest(unittest.TestCase):
|
|
|
18
21
|
boto3.Session = MagicMock(return_value='MOAR BOTO')
|
|
19
22
|
|
|
20
23
|
assume_role = AssumeRole(role_arn='aws:arn:role/name', external_id='12345')
|
|
21
|
-
self.
|
|
24
|
+
self.assertEqual("MOAR BOTO", assume_role(boto3))
|
|
22
25
|
boto3.client.assert_called_with("sts")
|
|
23
26
|
boto3.Session.assert_called_with(
|
|
24
27
|
aws_access_key_id="access-key",
|
|
@@ -54,7 +57,7 @@ class AssumeRoleTest(unittest.TestCase):
|
|
|
54
57
|
role_session_name="sup",
|
|
55
58
|
duration=7200,
|
|
56
59
|
)
|
|
57
|
-
self.
|
|
60
|
+
self.assertEqual("MOAR BOTO", assume_role("not-boto3"))
|
|
58
61
|
boto3.client.assert_called_with("sts")
|
|
59
62
|
boto3.Session.assert_called_with(
|
|
60
63
|
aws_access_key_id="access-key",
|
|
@@ -1,2 +1,12 @@
|
|
|
1
1
|
from .dynamo_db_backend import DynamoDBBackend
|
|
2
|
+
from .dynamo_db_parti_ql_backend import DynamoDBPartiQLBackend, DynamoDBPartiQLCursor
|
|
3
|
+
from .dynamo_db_condition_parser import DynamoDBConditionParser
|
|
2
4
|
from .sqs_backend import SqsBackend
|
|
5
|
+
|
|
6
|
+
__all__ = [
|
|
7
|
+
"DynamoDBBackend",
|
|
8
|
+
"SqsBackend",
|
|
9
|
+
"DynamoDBPartiQLBackend",
|
|
10
|
+
"DynamoDBPartiQLCursor",
|
|
11
|
+
"DynamoDBConditionParser",
|
|
12
|
+
]
|
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
from clearskies.backends.backend import Backend
|
|
2
|
-
from boto3.dynamodb import conditions as dynamodb_conditions
|
|
3
|
-
from decimal import Decimal
|
|
4
|
-
from clearskies.column_types.float import Float
|
|
5
|
-
from clearskies.column_types.integer import Integer
|
|
6
|
-
from clearskies.column_types.boolean import Boolean
|
|
7
|
-
import json
|
|
8
1
|
import base64
|
|
2
|
+
import json
|
|
3
|
+
from decimal import Decimal
|
|
9
4
|
from typing import Any, Callable, Dict, List, Tuple
|
|
5
|
+
|
|
6
|
+
from boto3.dynamodb import conditions as dynamodb_conditions
|
|
10
7
|
from clearskies import model
|
|
11
8
|
from clearskies.autodoc.schema import String as AutoDocString
|
|
9
|
+
from clearskies.backends.backend import Backend
|
|
10
|
+
from clearskies.column_types.boolean import Boolean
|
|
11
|
+
from clearskies.column_types.float import Float
|
|
12
|
+
from clearskies.column_types.integer import Integer
|
|
13
|
+
|
|
14
|
+
|
|
12
15
|
class DynamoDBBackend(Backend):
|
|
13
16
|
"""
|
|
14
17
|
DynamoDB is complicated.
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import unittest
|
|
2
|
-
from unittest.mock import MagicMock
|
|
3
2
|
from collections import OrderedDict
|
|
4
|
-
from types import SimpleNamespace
|
|
5
3
|
from decimal import Decimal
|
|
6
|
-
from
|
|
4
|
+
from types import SimpleNamespace
|
|
5
|
+
from unittest.mock import MagicMock
|
|
6
|
+
|
|
7
7
|
import clearskies
|
|
8
|
-
from ..di import StandardDependencies
|
|
9
8
|
from boto3.dynamodb import conditions as dynamodb_conditions
|
|
9
|
+
|
|
10
|
+
from ..di import StandardDependencies
|
|
11
|
+
|
|
12
|
+
|
|
10
13
|
class User(clearskies.Model):
|
|
11
14
|
def __init__(self, dynamo_db_backend, columns):
|
|
12
15
|
super().__init__(dynamo_db_backend, columns)
|
|
@@ -87,24 +90,27 @@ class DynamoDBBackendTest(unittest.TestCase):
|
|
|
87
90
|
user.save({'name': 'sup', 'age': 5, 'category_id': '1-2-3-4'})
|
|
88
91
|
self.boto3.resource.assert_called_with('dynamodb', region_name='us-east-2')
|
|
89
92
|
self.dynamo_db.Table.assert_called_with('users')
|
|
90
|
-
self.
|
|
93
|
+
self.assertEqual(1, len(self.dynamo_db_table.put_item.call_args_list))
|
|
91
94
|
call = self.dynamo_db_table.put_item.call_args_list[0]
|
|
92
|
-
self.
|
|
93
|
-
self.
|
|
95
|
+
self.assertEqual((), call.args)
|
|
96
|
+
self.assertEqual(1, len(call.kwargs))
|
|
94
97
|
self.assertTrue('Item' in call.kwargs)
|
|
95
98
|
saved_data = call.kwargs['Item']
|
|
96
99
|
# we're doing this a bit weird because the UUIDs will generate random values.
|
|
97
100
|
# I could mock it, or I could just be lazy and grab it from the data I was given.
|
|
98
|
-
self.
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
self.
|
|
101
|
+
self.assertEqual(
|
|
102
|
+
{
|
|
103
|
+
"id": saved_data["id"],
|
|
104
|
+
"name": "sup",
|
|
105
|
+
"age": 5,
|
|
106
|
+
"category_id": "1-2-3-4",
|
|
107
|
+
},
|
|
108
|
+
saved_data,
|
|
109
|
+
)
|
|
110
|
+
self.assertEqual(saved_data["id"], user.id)
|
|
111
|
+
self.assertEqual(5, user.age)
|
|
112
|
+
self.assertEqual("1-2-3-4", user.category_id)
|
|
113
|
+
self.assertEqual("sup", user.name)
|
|
108
114
|
|
|
109
115
|
def test_update(self):
|
|
110
116
|
self.dynamo_db_table.update_item = MagicMock(
|
|
@@ -135,10 +141,10 @@ class DynamoDBBackendTest(unittest.TestCase):
|
|
|
135
141
|
},
|
|
136
142
|
ReturnValues="ALL_NEW",
|
|
137
143
|
)
|
|
138
|
-
self.
|
|
139
|
-
self.
|
|
140
|
-
self.
|
|
141
|
-
self.
|
|
144
|
+
self.assertEqual("1-2-3-4", user.id)
|
|
145
|
+
self.assertEqual("hello", user.name)
|
|
146
|
+
self.assertEqual(10, user.age)
|
|
147
|
+
self.assertEqual("1-2-3-5", user.category_id)
|
|
142
148
|
|
|
143
149
|
def test_delete(self):
|
|
144
150
|
self.dynamo_db_table.delete_item = MagicMock()
|
|
@@ -158,24 +164,24 @@ class DynamoDBBackendTest(unittest.TestCase):
|
|
|
158
164
|
users = self.di.build(Users)
|
|
159
165
|
user = users.where('id=1-2-3-4').first()
|
|
160
166
|
self.assertTrue(user.exists)
|
|
161
|
-
self.
|
|
162
|
-
self.
|
|
163
|
-
self.
|
|
164
|
-
self.
|
|
167
|
+
self.assertEqual("1-2-3-4", user.id)
|
|
168
|
+
self.assertEqual(10, user.age)
|
|
169
|
+
self.assertEqual("4-5-6", user.category_id)
|
|
170
|
+
self.assertEqual(1, len(self.dynamo_db_table.query.call_args_list))
|
|
165
171
|
call = self.dynamo_db_table.query.call_args_list[0]
|
|
166
|
-
self.
|
|
167
|
-
self.
|
|
168
|
-
self.
|
|
172
|
+
self.assertEqual(3, len(call.kwargs))
|
|
173
|
+
self.assertEqual("ALL_ATTRIBUTES", call.kwargs["Select"])
|
|
174
|
+
self.assertEqual(True, call.kwargs["ScanIndexForward"])
|
|
169
175
|
key_condition = call.kwargs['KeyConditionExpression']
|
|
170
176
|
|
|
171
177
|
# dynamodb does not make it easy to verify that the key expression was built properly,
|
|
172
178
|
# and I don't think that mocking will make this any better. Hoepfully they don't
|
|
173
179
|
# change their library often...
|
|
174
180
|
key_column = key_condition.get_expression()['values'][0]
|
|
175
|
-
self.
|
|
181
|
+
self.assertEqual("id", key_column.name)
|
|
176
182
|
self.assertTrue(isinstance(key_column, dynamodb_conditions.Key))
|
|
177
|
-
self.
|
|
178
|
-
self.
|
|
183
|
+
self.assertEqual("=", key_condition.expression_operator)
|
|
184
|
+
self.assertEqual("1-2-3-4", key_condition.get_expression()["values"][1])
|
|
179
185
|
|
|
180
186
|
def test_fetch_by_id_with_sort(self):
|
|
181
187
|
self.dynamo_db_table.query = MagicMock(
|
|
@@ -187,22 +193,22 @@ class DynamoDBBackendTest(unittest.TestCase):
|
|
|
187
193
|
)
|
|
188
194
|
users = self.di.build(Users)
|
|
189
195
|
users = users.where('id=1-2-3-4').sort_by('category_id', 'desc').__iter__()
|
|
190
|
-
self.
|
|
196
|
+
self.assertEqual(1, len(self.dynamo_db_table.query.call_args_list))
|
|
191
197
|
call = self.dynamo_db_table.query.call_args_list[0]
|
|
192
|
-
self.
|
|
193
|
-
self.
|
|
194
|
-
self.
|
|
195
|
-
self.
|
|
198
|
+
self.assertEqual(4, len(call.kwargs))
|
|
199
|
+
self.assertEqual("ALL_ATTRIBUTES", call.kwargs["Select"])
|
|
200
|
+
self.assertEqual("id-category_id-index", call.kwargs["IndexName"])
|
|
201
|
+
self.assertEqual(False, call.kwargs["ScanIndexForward"])
|
|
196
202
|
key_condition = call.kwargs['KeyConditionExpression']
|
|
197
203
|
|
|
198
204
|
# dynamodb does not make it easy to verify that the key expression was built properly,
|
|
199
205
|
# and I don't think that mocking will make this any better. Hoepfully they don't
|
|
200
206
|
# change their library often...
|
|
201
207
|
key_column = key_condition.get_expression()['values'][0]
|
|
202
|
-
self.
|
|
208
|
+
self.assertEqual("id", key_column.name)
|
|
203
209
|
self.assertTrue(isinstance(key_column, dynamodb_conditions.Key))
|
|
204
|
-
self.
|
|
205
|
-
self.
|
|
210
|
+
self.assertEqual("=", key_condition.expression_operator)
|
|
211
|
+
self.assertEqual("1-2-3-4", key_condition.get_expression()["values"][1])
|
|
206
212
|
|
|
207
213
|
def test_fetch_by_secondary_index_twice(self):
|
|
208
214
|
self.dynamo_db_table.query = MagicMock(
|
|
@@ -214,12 +220,12 @@ class DynamoDBBackendTest(unittest.TestCase):
|
|
|
214
220
|
)
|
|
215
221
|
users = self.di.build(Users)
|
|
216
222
|
users = users.where('category_id=1-2-3-4').where('age>10').__iter__()
|
|
217
|
-
self.
|
|
223
|
+
self.assertEqual(1, len(self.dynamo_db_table.query.call_args_list))
|
|
218
224
|
call = self.dynamo_db_table.query.call_args_list[0]
|
|
219
|
-
self.
|
|
220
|
-
self.
|
|
221
|
-
self.
|
|
222
|
-
self.
|
|
225
|
+
self.assertEqual(4, len(call.kwargs))
|
|
226
|
+
self.assertEqual("ALL_ATTRIBUTES", call.kwargs["Select"])
|
|
227
|
+
self.assertEqual("category_id-age-index", call.kwargs["IndexName"])
|
|
228
|
+
self.assertEqual(True, call.kwargs["ScanIndexForward"])
|
|
223
229
|
key_condition = call.kwargs['KeyConditionExpression']
|
|
224
230
|
self.assertTrue(isinstance(key_condition, dynamodb_conditions.And))
|
|
225
231
|
gt_condition = key_condition.get_expression()['values'][0]
|
|
@@ -227,17 +233,17 @@ class DynamoDBBackendTest(unittest.TestCase):
|
|
|
227
233
|
|
|
228
234
|
self.assertTrue(isinstance(equal_condition, dynamodb_conditions.Equals))
|
|
229
235
|
key_column = equal_condition.get_expression()['values'][0]
|
|
230
|
-
self.
|
|
236
|
+
self.assertEqual("category_id", key_column.name)
|
|
231
237
|
self.assertTrue(isinstance(key_column, dynamodb_conditions.Key))
|
|
232
|
-
self.
|
|
233
|
-
self.
|
|
238
|
+
self.assertEqual("=", equal_condition.expression_operator)
|
|
239
|
+
self.assertEqual("1-2-3-4", equal_condition.get_expression()["values"][1])
|
|
234
240
|
|
|
235
241
|
self.assertTrue(isinstance(gt_condition, dynamodb_conditions.GreaterThan))
|
|
236
242
|
key_column = gt_condition.get_expression()['values'][0]
|
|
237
|
-
self.
|
|
243
|
+
self.assertEqual("age", key_column.name)
|
|
238
244
|
self.assertTrue(isinstance(key_column, dynamodb_conditions.Key))
|
|
239
|
-
self.
|
|
240
|
-
self.
|
|
245
|
+
self.assertEqual(">", gt_condition.expression_operator)
|
|
246
|
+
self.assertEqual(Decimal("10"), gt_condition.get_expression()["values"][1])
|
|
241
247
|
|
|
242
248
|
def test_index_and_scan(self):
|
|
243
249
|
self.dynamo_db_table.query = MagicMock(
|
|
@@ -249,27 +255,27 @@ class DynamoDBBackendTest(unittest.TestCase):
|
|
|
249
255
|
)
|
|
250
256
|
users = self.di.build(Users)
|
|
251
257
|
users = users.where('category_id=1-2-3-4').where('age is not null').__iter__()
|
|
252
|
-
self.
|
|
258
|
+
self.assertEqual(1, len(self.dynamo_db_table.query.call_args_list))
|
|
253
259
|
call = self.dynamo_db_table.query.call_args_list[0]
|
|
254
|
-
self.
|
|
255
|
-
self.
|
|
256
|
-
self.
|
|
257
|
-
self.
|
|
260
|
+
self.assertEqual(5, len(call.kwargs))
|
|
261
|
+
self.assertEqual("ALL_ATTRIBUTES", call.kwargs["Select"])
|
|
262
|
+
self.assertEqual("category_id-name-index", call.kwargs["IndexName"])
|
|
263
|
+
self.assertEqual(True, call.kwargs["ScanIndexForward"])
|
|
258
264
|
|
|
259
265
|
# our key condition should be an equal search on category_id
|
|
260
266
|
key_condition = call.kwargs['KeyConditionExpression']
|
|
261
267
|
key_column = key_condition.get_expression()['values'][0]
|
|
262
|
-
self.
|
|
268
|
+
self.assertEqual("category_id", key_column.name)
|
|
263
269
|
self.assertTrue(isinstance(key_column, dynamodb_conditions.Key))
|
|
264
|
-
self.
|
|
265
|
-
self.
|
|
270
|
+
self.assertEqual("=", key_condition.expression_operator)
|
|
271
|
+
self.assertEqual("1-2-3-4", key_condition.get_expression()["values"][1])
|
|
266
272
|
|
|
267
273
|
# and we should have a FilterExpression which is an 'is not null' condition
|
|
268
274
|
filter_condition = call.kwargs['FilterExpression']
|
|
269
275
|
key_column = filter_condition.get_expression()['values'][0]
|
|
270
|
-
self.
|
|
276
|
+
self.assertEqual("age", key_column.name)
|
|
271
277
|
self.assertTrue(isinstance(key_column, dynamodb_conditions.Attr))
|
|
272
|
-
self.
|
|
278
|
+
self.assertEqual("attribute_not_exists", filter_condition.expression_operator)
|
|
273
279
|
|
|
274
280
|
def test_scan_only(self):
|
|
275
281
|
self.dynamo_db_table.scan = MagicMock(
|
|
@@ -281,14 +287,14 @@ class DynamoDBBackendTest(unittest.TestCase):
|
|
|
281
287
|
)
|
|
282
288
|
users = self.di.build(Users)
|
|
283
289
|
users = users.where('category_id>1-2-3-4').__iter__()
|
|
284
|
-
self.
|
|
290
|
+
self.assertEqual(1, len(self.dynamo_db_table.scan.call_args_list))
|
|
285
291
|
call = self.dynamo_db_table.scan.call_args_list[0]
|
|
286
|
-
self.
|
|
287
|
-
self.
|
|
292
|
+
self.assertEqual(2, len(call.kwargs))
|
|
293
|
+
self.assertEqual("ALL_ATTRIBUTES", call.kwargs["Select"])
|
|
288
294
|
|
|
289
295
|
# and we should have a FilterExpression which is an 'is not null' condition
|
|
290
296
|
filter_condition = call.kwargs['FilterExpression']
|
|
291
297
|
key_column = filter_condition.get_expression()['values'][0]
|
|
292
|
-
self.
|
|
298
|
+
self.assertEqual("category_id", key_column.name)
|
|
293
299
|
self.assertTrue(isinstance(key_column, dynamodb_conditions.Attr))
|
|
294
|
-
self.
|
|
300
|
+
self.assertEqual(">", filter_condition.expression_operator)
|