Coverage for dynamodx / transact_get.py: 100%
41 statements
« prev ^ index » next coverage.py v7.13.2, created at 2026-02-18 12:56 -0300
« prev ^ index » next coverage.py v7.13.2, created at 2026-02-18 12:56 -0300
1from typing import TYPE_CHECKING, Any
3import jmespath
5from dynamodx.keys import PrimaryKey, PrimaryKeySet
6from dynamodx.types import deserialize, serialize
8if TYPE_CHECKING:
9 from mypy_boto3_dynamodb.client import DynamoDBClient
10 from mypy_boto3_dynamodb.type_defs import GetTypeDef, TransactGetItemTypeDef
12else:
13 DynamoDBClient = Any
14 GetTypeDef = Any
15 TransactGetItemTypeDef = Any
18class TransactGet:
19 def __init__(
20 self,
21 table_name: str,
22 *,
23 client: DynamoDBClient,
24 ) -> None:
25 self._table_name = table_name
26 self._client = client
28 def get_items(
29 self,
30 keyset: PrimaryKeySet,
31 *,
32 flatten_top: bool = True,
33 ) -> dict[str, Any]:
34 """Get multiple items via a transaction based on the provided TransactKey.
36 Parameters
37 ----------
38 key : PrimaryKeySet
40 flatten_top : bool, optional
41 Determines whether the first nested item in the transaction result
42 should be flattened,
43 i.e., extracted to serve as the primary item at the top level of
44 the returned dict.
45 If True, the nested item is promoted to the top level.
47 Returns
48 -------
49 dict[str, Any]
50 A dict of items retrieved from the transaction.
51 """
52 table_name = self._table_name
53 transact_items: list[TransactGetItemTypeDef] = [
54 _build_get(pk, table_name) for pk in keyset.pairs
55 ]
57 output = self._client.transact_get_items(TransactItems=transact_items)
58 items = [deserialize(r.get('Item', {})) for r in output.get('Responses', [])]
60 if flatten_top and items:
61 head, tail = items[0], items[1:]
62 else:
63 head, tail = {}, items
65 pairs = keyset.pairs[1:] if flatten_top else keyset.pairs
66 nested = {
67 _output_key(pk): _project_item(pk, item)
68 for pk, item in zip(pairs, tail, strict=True)
69 if item
70 }
72 return {**head, **nested}
75def _build_get(pk: PrimaryKey, table_name: str) -> TransactGetItemTypeDef:
76 sk = pk[pk.name_sk]
77 attrs: GetTypeDef = {
78 'TableName': pk.table_name or table_name,
79 'Key': serialize(pk),
80 }
82 projection_expr = getattr(sk, 'projection_expr', None)
83 expr_attr_names = getattr(sk, 'expr_attr_names', None)
85 if projection_expr is not None:
86 attrs['ProjectionExpression'] = projection_expr
88 if expr_attr_names is not None:
89 attrs['ExpressionAttributeNames'] = expr_attr_names
91 return {'Get': attrs}
94def _output_key(pk: PrimaryKey) -> str:
95 sk = pk.sk
96 return str(getattr(sk, 'rename_key', sk))
99def _project_item(pk: PrimaryKey, item: dict) -> dict:
100 sk = pk.sk
101 path_spec = getattr(sk, 'path_spec', None)
103 if path_spec is None:
104 return item
106 return jmespath.compile(path_spec).search(item)