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,3 @@
1
+ from robot_dynamodb.library import DynamoDbLibrary
2
+
3
+ __all__ = ["DynamoDbLibrary"]
@@ -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
+ )
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,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.30.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any