robot-dynamodb 0.1.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.
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
from typing import Any, Protocol, cast
|
|
2
|
+
|
|
3
|
+
import boto3
|
|
4
|
+
from robot.api.deco import keyword, library
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class DynamoDBTable(Protocol):
|
|
8
|
+
key_schema: list[dict[str, str]]
|
|
9
|
+
|
|
10
|
+
def put_item(self, Item: dict[str, Any], **kwargs: Any) -> dict[str, Any]: ...
|
|
11
|
+
def get_item(self, Key: dict[str, Any], **kwargs: Any) -> dict[str, Any]: ...
|
|
12
|
+
def update_item(self, Key: dict[str, Any], **kwargs: Any) -> dict[str, Any]: ...
|
|
13
|
+
def delete_item(self, Key: dict[str, Any], **kwargs: Any) -> dict[str, Any]: ...
|
|
14
|
+
def scan(self, **kwargs: Any) -> dict[str, Any]: ...
|
|
15
|
+
def query(self, **kwargs: Any) -> dict[str, Any]: ...
|
|
16
|
+
def batch_writer(self) -> Any: ...
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class DynamoDBResource(Protocol):
|
|
20
|
+
def Table(self, name: str) -> DynamoDBTable: ...
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@library(scope="SUITE")
|
|
24
|
+
class DynamoDbLibrary:
|
|
25
|
+
_resource: DynamoDBResource | None
|
|
26
|
+
_table_prefix: str
|
|
27
|
+
_table_postfix: str
|
|
28
|
+
|
|
29
|
+
def __init__(self) -> None:
|
|
30
|
+
self._resource = None
|
|
31
|
+
self._table_prefix = ""
|
|
32
|
+
self._table_postfix = ""
|
|
33
|
+
|
|
34
|
+
def _get_resource(self) -> DynamoDBResource:
|
|
35
|
+
if self._resource is None:
|
|
36
|
+
raise RuntimeError("Not connected. Call 'Connect To DynamoDB' first.")
|
|
37
|
+
return self._resource
|
|
38
|
+
|
|
39
|
+
def _table(self, table_name: str) -> DynamoDBTable:
|
|
40
|
+
return self._get_resource().Table(
|
|
41
|
+
f"{self._table_prefix}{table_name}{self._table_postfix}"
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
@keyword
|
|
45
|
+
def connect_to_dynamodb(
|
|
46
|
+
self,
|
|
47
|
+
endpoint_url: str,
|
|
48
|
+
region: str = "us-east-1",
|
|
49
|
+
table_prefix: str = "",
|
|
50
|
+
table_postfix: str = "",
|
|
51
|
+
aws_access_key_id: str = "test",
|
|
52
|
+
aws_secret_access_key: str = "test",
|
|
53
|
+
) -> None:
|
|
54
|
+
self._table_prefix = table_prefix
|
|
55
|
+
self._table_postfix = table_postfix
|
|
56
|
+
self._resource = cast(
|
|
57
|
+
DynamoDBResource,
|
|
58
|
+
boto3.resource(
|
|
59
|
+
"dynamodb",
|
|
60
|
+
endpoint_url=endpoint_url,
|
|
61
|
+
region_name=region,
|
|
62
|
+
aws_access_key_id=aws_access_key_id,
|
|
63
|
+
aws_secret_access_key=aws_secret_access_key,
|
|
64
|
+
),
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
@keyword
|
|
68
|
+
def disconnect_from_dynamodb(self) -> None:
|
|
69
|
+
self._resource = None
|
|
70
|
+
self._table_prefix = ""
|
|
71
|
+
self._table_postfix = ""
|
|
72
|
+
|
|
73
|
+
@keyword
|
|
74
|
+
def create_dynamodb_item(self, table_name: str, item: dict[str, Any]) -> dict[str, Any]:
|
|
75
|
+
self._table(table_name).put_item(Item=item)
|
|
76
|
+
return item
|
|
77
|
+
|
|
78
|
+
@keyword
|
|
79
|
+
def get_dynamodb_item(self, table_name: str, key: dict[str, Any]) -> dict[str, Any] | None:
|
|
80
|
+
return self._table(table_name).get_item(Key=key).get("Item")
|
|
81
|
+
|
|
82
|
+
@keyword
|
|
83
|
+
def update_dynamodb_item(
|
|
84
|
+
self,
|
|
85
|
+
table_name: str,
|
|
86
|
+
key: dict[str, Any],
|
|
87
|
+
update_expression: str,
|
|
88
|
+
expression_attribute_values: dict[str, Any],
|
|
89
|
+
expression_attribute_names: dict[str, str] | None = None,
|
|
90
|
+
) -> dict[str, Any]:
|
|
91
|
+
kwargs: dict[str, Any] = {
|
|
92
|
+
"Key": key,
|
|
93
|
+
"UpdateExpression": update_expression,
|
|
94
|
+
"ExpressionAttributeValues": expression_attribute_values,
|
|
95
|
+
}
|
|
96
|
+
if expression_attribute_names:
|
|
97
|
+
kwargs["ExpressionAttributeNames"] = expression_attribute_names
|
|
98
|
+
return self._table(table_name).update_item(**kwargs)
|
|
99
|
+
|
|
100
|
+
@keyword
|
|
101
|
+
def delete_dynamodb_item(self, table_name: str, key: dict[str, Any]) -> None:
|
|
102
|
+
self._table(table_name).delete_item(Key=key)
|
|
103
|
+
|
|
104
|
+
@keyword
|
|
105
|
+
def scan_dynamodb_table(self, table_name: str) -> list[dict[str, Any]]:
|
|
106
|
+
return self._table(table_name).scan().get("Items", [])
|
|
107
|
+
|
|
108
|
+
@keyword
|
|
109
|
+
def query_dynamodb_table(
|
|
110
|
+
self,
|
|
111
|
+
table_name: str,
|
|
112
|
+
key_condition_expression: str,
|
|
113
|
+
expression_attribute_values: dict[str, Any],
|
|
114
|
+
expression_attribute_names: dict[str, str] | None = None,
|
|
115
|
+
) -> list[dict[str, Any]]:
|
|
116
|
+
kwargs: dict[str, Any] = {
|
|
117
|
+
"KeyConditionExpression": key_condition_expression,
|
|
118
|
+
"ExpressionAttributeValues": expression_attribute_values,
|
|
119
|
+
}
|
|
120
|
+
if expression_attribute_names:
|
|
121
|
+
kwargs["ExpressionAttributeNames"] = expression_attribute_names
|
|
122
|
+
return self._table(table_name).query(**kwargs).get("Items", [])
|
|
123
|
+
|
|
124
|
+
@keyword
|
|
125
|
+
def truncate_dynamodb_table(self, table_name: str) -> None:
|
|
126
|
+
table = self._table(table_name)
|
|
127
|
+
key_names = {k["AttributeName"] for k in table.key_schema}
|
|
128
|
+
items = table.scan().get("Items", [])
|
|
129
|
+
with table.batch_writer() as batch:
|
|
130
|
+
for item in items:
|
|
131
|
+
batch.delete_item(Key={k: v for k, v in item.items() if k in key_names})
|
|
132
|
+
|
|
133
|
+
@keyword
|
|
134
|
+
def batch_write_dynamodb_items(
|
|
135
|
+
self, table_name: str, items: list[dict[str, Any]]
|
|
136
|
+
) -> None:
|
|
137
|
+
table = self._table(table_name)
|
|
138
|
+
with table.batch_writer() as batch:
|
|
139
|
+
for item in items:
|
|
140
|
+
batch.put_item(Item=item)
|
|
141
|
+
|
|
142
|
+
@keyword
|
|
143
|
+
def item_should_exist_in_dynamodb(
|
|
144
|
+
self, table_name: str, key: dict[str, Any]
|
|
145
|
+
) -> dict[str, Any]:
|
|
146
|
+
item = self.get_dynamodb_item(table_name, key)
|
|
147
|
+
if item is None:
|
|
148
|
+
full = f"{self._table_prefix}{table_name}{self._table_postfix}"
|
|
149
|
+
raise AssertionError(f"Item {key} not found in table '{full}'")
|
|
150
|
+
return item
|
|
151
|
+
|
|
152
|
+
@keyword
|
|
153
|
+
def item_should_not_exist_in_dynamodb(
|
|
154
|
+
self, table_name: str, key: dict[str, Any]
|
|
155
|
+
) -> None:
|
|
156
|
+
item = self.get_dynamodb_item(table_name, key)
|
|
157
|
+
if item is not None:
|
|
158
|
+
full = f"{self._table_prefix}{table_name}{self._table_postfix}"
|
|
159
|
+
raise AssertionError(
|
|
160
|
+
f"Item {key} found in table '{full}' but should not exist"
|
|
161
|
+
)
|
robot_dynamodb/py.typed
ADDED
|
File without changes
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: robot-dynamodb
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Robot Framework library for DynamoDB (LocalStack and AWS)
|
|
5
|
+
Author-email: Leandro Santiago Gomes <leandroluk@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: >=3.14
|
|
8
|
+
Requires-Dist: boto3>=1.34.0
|
|
9
|
+
Requires-Dist: robotframework>=7.0.0
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
|
|
12
|
+
# robot-dynamodb
|
|
13
|
+
|
|
14
|
+
Robot Framework library for DynamoDB. Works with LocalStack and AWS.
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pip install robot-dynamodb
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
```robot
|
|
25
|
+
*** Settings ***
|
|
26
|
+
Library robot_dynamodb.DynamoDbLibrary
|
|
27
|
+
|
|
28
|
+
Suite Setup Connect To DynamoDB
|
|
29
|
+
... endpoint_url=http://localhost:4566
|
|
30
|
+
... region=sa-east-1
|
|
31
|
+
... table_prefix=dev_
|
|
32
|
+
... table_postfix=_v1
|
|
33
|
+
Suite Teardown Disconnect From DynamoDB
|
|
34
|
+
|
|
35
|
+
Test Setup Truncate DynamoDB Table orders
|
|
36
|
+
Test Teardown Truncate DynamoDB Table orders
|
|
37
|
+
|
|
38
|
+
*** Test Cases ***
|
|
39
|
+
Pedido deve ser persistido
|
|
40
|
+
Batch Write DynamoDB Items orders ${seed_items}
|
|
41
|
+
Item Should Exist In DynamoDB orders {"id": "123"}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Keywords
|
|
45
|
+
|
|
46
|
+
| Keyword | Descrição |
|
|
47
|
+
|---|---|
|
|
48
|
+
| `Connect To DynamoDB` | Cria conexão boto3 |
|
|
49
|
+
| `Disconnect From DynamoDB` | Limpa estado |
|
|
50
|
+
| `Create DynamoDB Item` | Insere item (`put_item`) |
|
|
51
|
+
| `Get DynamoDB Item` | Busca por chave |
|
|
52
|
+
| `Update DynamoDB Item` | Atualiza atributos |
|
|
53
|
+
| `Delete DynamoDB Item` | Remove por chave |
|
|
54
|
+
| `Scan DynamoDB Table` | Lista todos os items |
|
|
55
|
+
| `Query DynamoDB Table` | Busca por partition key |
|
|
56
|
+
| `Truncate DynamoDB Table` | Deleta todos os items |
|
|
57
|
+
| `Batch Write DynamoDB Items` | Insere lista de items |
|
|
58
|
+
| `Item Should Exist In DynamoDB` | Falha se item não encontrado |
|
|
59
|
+
| `Item Should Not Exist In DynamoDB` | Falha se item encontrado |
|
|
60
|
+
|
|
61
|
+
## Connect To DynamoDB Parameters
|
|
62
|
+
|
|
63
|
+
| Parâmetro | Default | Descrição |
|
|
64
|
+
|---|---|---|
|
|
65
|
+
| `endpoint_url` | — | URL do DynamoDB / LocalStack |
|
|
66
|
+
| `region` | `us-east-1` | AWS region |
|
|
67
|
+
| `table_prefix` | `""` | Prefixo do nome da tabela |
|
|
68
|
+
| `table_postfix` | `""` | Sufixo do nome da tabela |
|
|
69
|
+
| `aws_access_key_id` | `test` | AWS / LocalStack key |
|
|
70
|
+
| `aws_secret_access_key` | `test` | AWS / LocalStack secret |
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
robot_dynamodb/__init__.py,sha256=1NJx7N8CdshADcgyp6mWM5WjoWp0-Nh18fxv6sqN9R4,82
|
|
2
|
+
robot_dynamodb/library.py,sha256=09KJfud2eTpV6frV3LVQCgz9WtfMqWxrTaJq0wKD_tE,5664
|
|
3
|
+
robot_dynamodb/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
robot_dynamodb-0.1.0.dist-info/METADATA,sha256=h-7hIpc51GdM2Eutso0RuxrPfALQj4DxBFwje9P_OXk,2119
|
|
5
|
+
robot_dynamodb-0.1.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
6
|
+
robot_dynamodb-0.1.0.dist-info/RECORD,,
|