fluidattacks_integrates_dal 2.3.1__tar.gz → 2.3.2__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.
- {fluidattacks_integrates_dal-2.3.1 → fluidattacks_integrates_dal-2.3.2}/PKG-INFO +2 -1
- {fluidattacks_integrates_dal-2.3.1 → fluidattacks_integrates_dal-2.3.2}/build/default.nix +4 -8
- {fluidattacks_integrates_dal-2.3.1 → fluidattacks_integrates_dal-2.3.2}/flake.lock +22 -60
- {fluidattacks_integrates_dal-2.3.1 → fluidattacks_integrates_dal-2.3.2}/flake.nix +3 -4
- {fluidattacks_integrates_dal-2.3.1 → fluidattacks_integrates_dal-2.3.2}/fluidattacks_integrates_dal/__init__.py +1 -1
- {fluidattacks_integrates_dal-2.3.1 → fluidattacks_integrates_dal-2.3.2}/fluidattacks_integrates_dal/_cli.py +4 -4
- fluidattacks_integrates_dal-2.3.2/fluidattacks_integrates_dal/_typing.py +11 -0
- {fluidattacks_integrates_dal-2.3.1 → fluidattacks_integrates_dal-2.3.2}/fluidattacks_integrates_dal/clients/group/__init__.py +2 -2
- {fluidattacks_integrates_dal-2.3.1 → fluidattacks_integrates_dal-2.3.2}/fluidattacks_integrates_dal/clients/organization/__init__.py +27 -18
- {fluidattacks_integrates_dal-2.3.1 → fluidattacks_integrates_dal-2.3.2}/fluidattacks_integrates_dal/clients/out_of_scope/__init__.py +2 -2
- {fluidattacks_integrates_dal-2.3.1 → fluidattacks_integrates_dal-2.3.2}/fluidattacks_integrates_dal/core.py +9 -7
- fluidattacks_integrates_dal-2.3.2/fluidattacks_integrates_dal/utils.py +38 -0
- {fluidattacks_integrates_dal-2.3.1 → fluidattacks_integrates_dal-2.3.2}/pyproject.toml +3 -2
- {fluidattacks_integrates_dal-2.3.1 → fluidattacks_integrates_dal-2.3.2}/tests/arch/arch.py +3 -8
- {fluidattacks_integrates_dal-2.3.1 → fluidattacks_integrates_dal-2.3.2}/tests/arch/test_arch.py +2 -2
- {fluidattacks_integrates_dal-2.3.1 → fluidattacks_integrates_dal-2.3.2}/tests/test_list_groups.py +6 -2
- {fluidattacks_integrates_dal-2.3.1 → fluidattacks_integrates_dal-2.3.2}/uv.lock +295 -278
- fluidattacks_integrates_dal-2.3.1/fluidattacks_integrates_dal/_typing.py +0 -17
- fluidattacks_integrates_dal-2.3.1/fluidattacks_integrates_dal/utils.py +0 -32
- {fluidattacks_integrates_dal-2.3.1 → fluidattacks_integrates_dal-2.3.2}/.envrc +0 -0
- {fluidattacks_integrates_dal-2.3.1 → fluidattacks_integrates_dal-2.3.2}/build/filter.nix +0 -0
- {fluidattacks_integrates_dal-2.3.1 → fluidattacks_integrates_dal-2.3.2}/fluidattacks_integrates_dal/_logger.py +0 -0
- {fluidattacks_integrates_dal-2.3.1 → fluidattacks_integrates_dal-2.3.2}/fluidattacks_integrates_dal/client.py +0 -0
- {fluidattacks_integrates_dal-2.3.1 → fluidattacks_integrates_dal-2.3.2}/fluidattacks_integrates_dal/clients/__init__.py +0 -0
- {fluidattacks_integrates_dal-2.3.1 → fluidattacks_integrates_dal-2.3.2}/fluidattacks_integrates_dal/list_groups.py +0 -0
- {fluidattacks_integrates_dal-2.3.1 → fluidattacks_integrates_dal-2.3.2}/fluidattacks_integrates_dal/py.typed +0 -0
- {fluidattacks_integrates_dal-2.3.1 → fluidattacks_integrates_dal-2.3.2}/mypy.ini +0 -0
- {fluidattacks_integrates_dal-2.3.1 → fluidattacks_integrates_dal-2.3.2}/ruff.toml +0 -0
- {fluidattacks_integrates_dal-2.3.1 → fluidattacks_integrates_dal-2.3.2}/tests/__init__.py +0 -0
- {fluidattacks_integrates_dal-2.3.1 → fluidattacks_integrates_dal-2.3.2}/tests/arch/__init__.py +0 -0
- {fluidattacks_integrates_dal-2.3.1 → fluidattacks_integrates_dal-2.3.2}/tests/py.typed +0 -0
- {fluidattacks_integrates_dal-2.3.1 → fluidattacks_integrates_dal-2.3.2}/tests/test_core.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fluidattacks_integrates_dal
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.2
|
|
4
4
|
Summary: ASM Synchronous Data Access Layer
|
|
5
5
|
Author-email: Engineering Team <development@fluidattacks.com>
|
|
6
6
|
Requires-Python: >=3.11
|
|
@@ -10,3 +10,4 @@ Requires-Dist: click >=8.1.7, <9.0.0
|
|
|
10
10
|
Requires-Dist: fa-purity >=2.5.2, <3.0.0
|
|
11
11
|
Requires-Dist: fluidattacks-etl-utils >=5.1.0, <6.0.0
|
|
12
12
|
Requires-Dist: fluidattacks-utils-logger >=3.0.0, <4.0.0
|
|
13
|
+
Requires-Dist: mypy-boto3-dynamodb >=1.40.40, <2.0.0
|
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
{
|
|
2
|
-
nixpkgs,
|
|
3
|
-
builders,
|
|
4
|
-
scripts,
|
|
5
|
-
src,
|
|
6
|
-
}:
|
|
1
|
+
{ src }:
|
|
7
2
|
{
|
|
8
3
|
inherit src;
|
|
9
4
|
root_path = "observes/common/integrates-dal";
|
|
10
5
|
module_name = "fluidattacks_integrates_dal";
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
pypi_token = {
|
|
7
|
+
method = "oidc";
|
|
8
|
+
};
|
|
13
9
|
}
|
|
@@ -98,11 +98,11 @@
|
|
|
98
98
|
},
|
|
99
99
|
"nixpkgs_flake": {
|
|
100
100
|
"locked": {
|
|
101
|
-
"lastModified":
|
|
102
|
-
"narHash": "sha256-
|
|
101
|
+
"lastModified": 1778253243,
|
|
102
|
+
"narHash": "sha256-KkH2QvU6iRLDTGGEwH5jnMqHWj4zMTuHxi1S1zdr01w=",
|
|
103
103
|
"owner": "nixos",
|
|
104
104
|
"repo": "nixpkgs",
|
|
105
|
-
"rev": "
|
|
105
|
+
"rev": "4fcda7103530b23c5ca44286344912082aad4220",
|
|
106
106
|
"type": "github"
|
|
107
107
|
},
|
|
108
108
|
"original": {
|
|
@@ -111,49 +111,6 @@
|
|
|
111
111
|
"type": "github"
|
|
112
112
|
}
|
|
113
113
|
},
|
|
114
|
-
"nixpkgs_flake_2": {
|
|
115
|
-
"locked": {
|
|
116
|
-
"lastModified": 1761668286,
|
|
117
|
-
"narHash": "sha256-YN/cm/hbm7pi7lMZCsNhu6jlBUi4wUirrIlyOMpbjKU=",
|
|
118
|
-
"owner": "nixos",
|
|
119
|
-
"repo": "nixpkgs",
|
|
120
|
-
"rev": "1fdb9eb10eff581a40ce2e9511c4ed517eac0c3f",
|
|
121
|
-
"type": "github"
|
|
122
|
-
},
|
|
123
|
-
"original": {
|
|
124
|
-
"owner": "nixos",
|
|
125
|
-
"repo": "nixpkgs",
|
|
126
|
-
"type": "github"
|
|
127
|
-
}
|
|
128
|
-
},
|
|
129
|
-
"observes_flake_builder": {
|
|
130
|
-
"inputs": {
|
|
131
|
-
"nix_filter": "nix_filter",
|
|
132
|
-
"nixpkgs_flake": "nixpkgs_flake",
|
|
133
|
-
"pyproject-build-systems": "pyproject-build-systems",
|
|
134
|
-
"pyproject-nix": "pyproject-nix_2",
|
|
135
|
-
"pythonix_flake": "pythonix_flake",
|
|
136
|
-
"shell-helpers": "shell-helpers",
|
|
137
|
-
"uv2nix": "uv2nix_2"
|
|
138
|
-
},
|
|
139
|
-
"locked": {
|
|
140
|
-
"dir": "observes/common/std_flake_2",
|
|
141
|
-
"lastModified": 1770672786,
|
|
142
|
-
"narHash": "sha256-W4qMpuS/Zg9P/PooFDsqW7EzjF3A+ITsxKbp1SWdARI=",
|
|
143
|
-
"ref": "refs/heads/trunk",
|
|
144
|
-
"rev": "ad927cc6545df64a7d622696a43bcee225b9867b",
|
|
145
|
-
"shallow": true,
|
|
146
|
-
"type": "git",
|
|
147
|
-
"url": "ssh://git@gitlab.com/fluidattacks/universe"
|
|
148
|
-
},
|
|
149
|
-
"original": {
|
|
150
|
-
"dir": "observes/common/std_flake_2",
|
|
151
|
-
"rev": "ad927cc6545df64a7d622696a43bcee225b9867b",
|
|
152
|
-
"shallow": true,
|
|
153
|
-
"type": "git",
|
|
154
|
-
"url": "ssh://git@gitlab.com/fluidattacks/universe"
|
|
155
|
-
}
|
|
156
|
-
},
|
|
157
114
|
"pyproject-build-systems": {
|
|
158
115
|
"inputs": {
|
|
159
116
|
"nixpkgs": "nixpkgs",
|
|
@@ -177,7 +134,7 @@
|
|
|
177
134
|
"pyproject-nix": {
|
|
178
135
|
"inputs": {
|
|
179
136
|
"nixpkgs": [
|
|
180
|
-
"
|
|
137
|
+
"python_builder",
|
|
181
138
|
"pyproject-build-systems",
|
|
182
139
|
"nixpkgs"
|
|
183
140
|
]
|
|
@@ -217,7 +174,7 @@
|
|
|
217
174
|
"pyproject-nix_3": {
|
|
218
175
|
"inputs": {
|
|
219
176
|
"nixpkgs": [
|
|
220
|
-
"
|
|
177
|
+
"python_builder",
|
|
221
178
|
"uv2nix",
|
|
222
179
|
"nixpkgs"
|
|
223
180
|
]
|
|
@@ -236,23 +193,28 @@
|
|
|
236
193
|
"type": "github"
|
|
237
194
|
}
|
|
238
195
|
},
|
|
239
|
-
"
|
|
196
|
+
"python_builder": {
|
|
240
197
|
"inputs": {
|
|
241
|
-
"
|
|
198
|
+
"nix_filter": "nix_filter",
|
|
199
|
+
"nixpkgs_flake": "nixpkgs_flake",
|
|
200
|
+
"pyproject-build-systems": "pyproject-build-systems",
|
|
201
|
+
"pyproject-nix": "pyproject-nix_2",
|
|
202
|
+
"shell-helpers": "shell-helpers",
|
|
203
|
+
"uv2nix": "uv2nix_2"
|
|
242
204
|
},
|
|
243
205
|
"locked": {
|
|
244
|
-
"dir": "
|
|
245
|
-
"lastModified":
|
|
246
|
-
"narHash": "sha256-
|
|
206
|
+
"dir": "common/utils/python-builder",
|
|
207
|
+
"lastModified": 1785790367,
|
|
208
|
+
"narHash": "sha256-Br5oTB6LNGANZMUecvZhlXpA0k0wb0EKmOqyQeYCe7A=",
|
|
247
209
|
"ref": "refs/heads/trunk",
|
|
248
|
-
"rev": "
|
|
210
|
+
"rev": "f66f38301987775ceb39ee72388ef0885ef30d13",
|
|
249
211
|
"shallow": true,
|
|
250
212
|
"type": "git",
|
|
251
213
|
"url": "ssh://git@gitlab.com/fluidattacks/universe"
|
|
252
214
|
},
|
|
253
215
|
"original": {
|
|
254
|
-
"dir": "
|
|
255
|
-
"rev": "
|
|
216
|
+
"dir": "common/utils/python-builder",
|
|
217
|
+
"rev": "f66f38301987775ceb39ee72388ef0885ef30d13",
|
|
256
218
|
"shallow": true,
|
|
257
219
|
"type": "git",
|
|
258
220
|
"url": "ssh://git@gitlab.com/fluidattacks/universe"
|
|
@@ -260,14 +222,14 @@
|
|
|
260
222
|
},
|
|
261
223
|
"root": {
|
|
262
224
|
"inputs": {
|
|
263
|
-
"
|
|
225
|
+
"python_builder": "python_builder"
|
|
264
226
|
}
|
|
265
227
|
},
|
|
266
228
|
"shell-helpers": {
|
|
267
229
|
"inputs": {
|
|
268
230
|
"flake-parts": "flake-parts",
|
|
269
231
|
"nixpkgs": [
|
|
270
|
-
"
|
|
232
|
+
"python_builder",
|
|
271
233
|
"nixpkgs_flake"
|
|
272
234
|
]
|
|
273
235
|
},
|
|
@@ -292,12 +254,12 @@
|
|
|
292
254
|
"uv2nix": {
|
|
293
255
|
"inputs": {
|
|
294
256
|
"nixpkgs": [
|
|
295
|
-
"
|
|
257
|
+
"python_builder",
|
|
296
258
|
"pyproject-build-systems",
|
|
297
259
|
"nixpkgs"
|
|
298
260
|
],
|
|
299
261
|
"pyproject-nix": [
|
|
300
|
-
"
|
|
262
|
+
"python_builder",
|
|
301
263
|
"pyproject-build-systems",
|
|
302
264
|
"pyproject-nix"
|
|
303
265
|
]
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
description = "Common Integrates-dal";
|
|
3
3
|
|
|
4
4
|
inputs = {
|
|
5
|
-
|
|
6
|
-
url = "git+ssh://git@gitlab.com/fluidattacks/universe?shallow=1&rev=
|
|
5
|
+
python_builder = {
|
|
6
|
+
url = "git+ssh://git@gitlab.com/fluidattacks/universe?shallow=1&rev=f66f38301987775ceb39ee72388ef0885ef30d13&dir=common/utils/python-builder";
|
|
7
7
|
};
|
|
8
8
|
};
|
|
9
9
|
|
|
@@ -19,11 +19,10 @@
|
|
|
19
19
|
scripts,
|
|
20
20
|
}:
|
|
21
21
|
import ./build {
|
|
22
|
-
inherit nixpkgs builders scripts;
|
|
23
22
|
src = import ./build/filter.nix nixpkgs.nix-filter self;
|
|
24
23
|
};
|
|
25
24
|
in
|
|
26
25
|
{
|
|
27
|
-
packages = inputs.
|
|
26
|
+
packages = inputs.python_builder.outputs.build build_args;
|
|
28
27
|
};
|
|
29
28
|
}
|
|
@@ -42,10 +42,10 @@ def list_all_groups() -> NoReturn:
|
|
|
42
42
|
list_groups.list_all_groups(t[0], t[1])
|
|
43
43
|
.map(lambda gs: "\n".join(g.name for g in gs))
|
|
44
44
|
.bind(
|
|
45
|
-
lambda s:
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
lambda _: None
|
|
45
|
+
lambda s: (
|
|
46
|
+
Cmd[int]
|
|
47
|
+
.wrap_impure(lambda: sys.stdout.write(s + "\n")) # type: ignore[misc]
|
|
48
|
+
.map(lambda _: None)
|
|
49
49
|
),
|
|
50
50
|
)
|
|
51
51
|
),
|
|
@@ -125,7 +125,7 @@ def _get_groups_page(
|
|
|
125
125
|
LOG.debug(page)
|
|
126
126
|
return page
|
|
127
127
|
|
|
128
|
-
return Cmd.wrap_impure(_action)
|
|
128
|
+
return Cmd[_Page].wrap_impure(_action)
|
|
129
129
|
|
|
130
130
|
|
|
131
131
|
def _get_groups(table: Table, org: OrganizationId) -> Stream[GroupId]:
|
|
@@ -137,7 +137,7 @@ def _get_groups(table: Table, org: OrganizationId) -> Stream[GroupId]:
|
|
|
137
137
|
lambda p: (
|
|
138
138
|
_get_groups_page(table, org, p.last_index).map(_union.inl)
|
|
139
139
|
if p and p.last_index
|
|
140
|
-
else Cmd.wrap_value(None).map(_union.inr)
|
|
140
|
+
else Cmd[None].wrap_value(None).map(_union.inr)
|
|
141
141
|
),
|
|
142
142
|
),
|
|
143
143
|
init.map(_union.inl),
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
-
from typing import
|
|
4
|
+
from typing import (
|
|
5
|
+
TYPE_CHECKING,
|
|
6
|
+
)
|
|
5
7
|
|
|
6
8
|
from fa_purity import (
|
|
7
9
|
Cmd,
|
|
@@ -20,9 +22,11 @@ from fa_purity.json import (
|
|
|
20
22
|
JsonPrimitiveFactory,
|
|
21
23
|
JsonPrimitiveUnfolder,
|
|
22
24
|
)
|
|
25
|
+
from mypy_boto3_dynamodb.type_defs import (
|
|
26
|
+
QueryOutputTypeDef,
|
|
27
|
+
)
|
|
23
28
|
|
|
24
29
|
from fluidattacks_integrates_dal._typing import (
|
|
25
|
-
Dict,
|
|
26
30
|
Iterable,
|
|
27
31
|
TypeVar,
|
|
28
32
|
)
|
|
@@ -37,37 +41,40 @@ if TYPE_CHECKING:
|
|
|
37
41
|
from mypy_boto3_dynamodb import (
|
|
38
42
|
DynamoDBClient,
|
|
39
43
|
)
|
|
40
|
-
from mypy_boto3_dynamodb.type_defs import (
|
|
41
|
-
QueryOutputTypeDef,
|
|
42
|
-
)
|
|
43
44
|
LOG = logging.getLogger(__name__)
|
|
44
45
|
_T = TypeVar("_T")
|
|
45
46
|
_K = TypeVar("_K")
|
|
46
47
|
_DB_TABLE = "integrates_vms"
|
|
47
48
|
|
|
48
49
|
|
|
49
|
-
def _require_key(item:
|
|
50
|
+
def _require_key(item: dict[_K, _T], key: _K) -> ResultE[_T]:
|
|
50
51
|
try:
|
|
51
|
-
return Result.success(item[key])
|
|
52
|
+
return Result[_T, Exception].success(item[key])
|
|
52
53
|
except KeyError as err:
|
|
53
|
-
return Result.failure(err).alt(cast_exception)
|
|
54
|
+
return Result[_T, KeyError].failure(err).alt(cast_exception)
|
|
54
55
|
|
|
55
56
|
|
|
56
|
-
def _decode_dynamo_str(item:
|
|
57
|
+
def _decode_dynamo_str(item: object) -> ResultE[JsonPrimitive]:
|
|
57
58
|
if isinstance(item, dict):
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
# isinstance narrows to dict[Unknown, Unknown]; the actual key/value
|
|
60
|
+
# types are only known by convention (DynamoDB's typed-attribute maps).
|
|
61
|
+
s_value: ResultE[str] = _require_key(
|
|
62
|
+
item, # pyright: ignore[reportUnknownArgumentType]
|
|
63
|
+
"S",
|
|
60
64
|
)
|
|
61
|
-
|
|
62
|
-
|
|
65
|
+
return s_value.bind(JsonPrimitiveFactory.from_any)
|
|
66
|
+
return (
|
|
67
|
+
Result[JsonPrimitive, TypeError]
|
|
68
|
+
.failure(TypeError(f"Expected `dict` instance; got `{type(item)}`"))
|
|
69
|
+
.alt(cast_exception)
|
|
63
70
|
)
|
|
64
71
|
|
|
65
72
|
|
|
66
|
-
def _decode_dynamo_key_str(item:
|
|
73
|
+
def _decode_dynamo_key_str(item: dict[str, _T], key: str) -> ResultE[JsonPrimitive]:
|
|
67
74
|
return _require_key(item, key).bind(_decode_dynamo_str)
|
|
68
75
|
|
|
69
76
|
|
|
70
|
-
def _decode_org_id(raw:
|
|
77
|
+
def _decode_org_id(raw: dict[str, _T]) -> ResultE[OrganizationId]:
|
|
71
78
|
_pk = _decode_dynamo_key_str(raw, "pk").bind(JsonPrimitiveUnfolder.to_str)
|
|
72
79
|
_sk = _decode_dynamo_key_str(raw, "sk").bind(JsonPrimitiveUnfolder.to_str)
|
|
73
80
|
return _pk.bind(lambda pk: _sk.bind(lambda sk: OrganizationId.new(pk, sk)))
|
|
@@ -85,7 +92,7 @@ def _to_items(page: QueryOutputTypeDef) -> FrozenList[OrganizationId]:
|
|
|
85
92
|
def _all_orgs(client: DynamoDBClient) -> Stream[OrganizationId]:
|
|
86
93
|
def _new_iter() -> Iterable[Cmd[QueryOutputTypeDef]]:
|
|
87
94
|
LOG.debug("Getting all orgs")
|
|
88
|
-
exp_attrs_values:
|
|
95
|
+
exp_attrs_values: dict[str, dict[str, str]] = {
|
|
89
96
|
":pk": {"S": "ORG#all"},
|
|
90
97
|
":sk": {"S": "ORG#"},
|
|
91
98
|
}
|
|
@@ -100,10 +107,12 @@ def _all_orgs(client: DynamoDBClient) -> Stream[OrganizationId]:
|
|
|
100
107
|
IndexName="gsi_2",
|
|
101
108
|
)
|
|
102
109
|
LOG.debug("all orgs retrieved!")
|
|
103
|
-
return
|
|
110
|
+
return (Cmd[QueryOutputTypeDef].wrap_value(v) for v in response) # type: ignore[misc]
|
|
104
111
|
|
|
105
112
|
data = StreamFactory.from_commands( # type: ignore[misc]
|
|
106
|
-
Unsafe.pure_iter_from_cmd(
|
|
113
|
+
Unsafe.pure_iter_from_cmd(
|
|
114
|
+
Cmd[Iterable[Cmd[QueryOutputTypeDef]]].wrap_impure(_new_iter), # type: ignore[misc]
|
|
115
|
+
),
|
|
107
116
|
)
|
|
108
117
|
return (
|
|
109
118
|
data.map(_to_items) # type: ignore[misc]
|
|
@@ -113,9 +113,9 @@ def _get_page(
|
|
|
113
113
|
.transform(PureIterTransform.filter_maybe)
|
|
114
114
|
.to_list()
|
|
115
115
|
)
|
|
116
|
-
return (roots, Maybe.from_optional(response.get("LastEvaluatedKey")))
|
|
116
|
+
return (roots, Maybe[_Cursor].from_optional(response.get("LastEvaluatedKey")))
|
|
117
117
|
|
|
118
|
-
return Cmd.wrap_impure(_action)
|
|
118
|
+
return Cmd[tuple[FrozenList[OutOfScopeRoot], Maybe[_Cursor]]].wrap_impure(_action)
|
|
119
119
|
|
|
120
120
|
|
|
121
121
|
def _get_roots(table: Table, org: OrganizationId) -> Stream[FrozenList[OutOfScopeRoot]]:
|
|
@@ -31,8 +31,8 @@ class GroupId:
|
|
|
31
31
|
pattern = r"^[\w\s-]+$"
|
|
32
32
|
if not re.match(pattern, _name):
|
|
33
33
|
err = ValueError(rf"Group name is not `^[\w- ]+$` i.e. {_name}")
|
|
34
|
-
return Result.failure(err
|
|
35
|
-
return Result.success(GroupId(_Private(), _name)
|
|
34
|
+
return Result[GroupId, ValueError].failure(err).alt(cast_exception)
|
|
35
|
+
return Result[GroupId, Exception].success(GroupId(_Private(), _name))
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
@dataclass(frozen=True)
|
|
@@ -47,13 +47,13 @@ class OrganizationId:
|
|
|
47
47
|
_uuid = uuid.removeprefix("ORG#")
|
|
48
48
|
if not _name.isalnum():
|
|
49
49
|
err = ValueError(f"Org name is not alphanum i.e. {_name}")
|
|
50
|
-
return Result.failure(err
|
|
50
|
+
return Result[OrganizationId, ValueError].failure(err).alt(cast_exception)
|
|
51
51
|
uuidv4 = "^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$"
|
|
52
52
|
if re.match(uuidv4, _uuid, re.IGNORECASE) is None:
|
|
53
53
|
err = ValueError(f"Org id is not an UUIDv4 i.e. {_uuid}")
|
|
54
|
-
return Result.failure(err
|
|
54
|
+
return Result[OrganizationId, ValueError].failure(err).alt(cast_exception)
|
|
55
55
|
|
|
56
|
-
return Result.success(OrganizationId(_Private(), _name, _uuid)
|
|
56
|
+
return Result[OrganizationId, Exception].success(OrganizationId(_Private(), _name, _uuid))
|
|
57
57
|
|
|
58
58
|
|
|
59
59
|
@dataclass(frozen=True)
|
|
@@ -66,5 +66,7 @@ class OutOfScopeRoot:
|
|
|
66
66
|
def new(nickname: str, status: str) -> ResultE[OutOfScopeRoot]:
|
|
67
67
|
if not nickname:
|
|
68
68
|
err = ValueError("Out-of-scope root nickname is empty")
|
|
69
|
-
return Result.failure(err
|
|
70
|
-
return Result
|
|
69
|
+
return Result[OutOfScopeRoot, ValueError].failure(err).alt(cast_exception)
|
|
70
|
+
return Result[OutOfScopeRoot, Exception].success(
|
|
71
|
+
OutOfScopeRoot(_Private(), nickname, status),
|
|
72
|
+
)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from boto3 import (
|
|
4
|
+
Session,
|
|
5
|
+
)
|
|
6
|
+
from fa_purity import (
|
|
7
|
+
Cmd,
|
|
8
|
+
)
|
|
9
|
+
from mypy_boto3_dynamodb import (
|
|
10
|
+
DynamoDBClient,
|
|
11
|
+
DynamoDBServiceResource,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def new_session() -> Cmd[Session]:
|
|
16
|
+
# This impure procedure gets inputs (credentials) through the environment
|
|
17
|
+
# e.g. AWS_DEFAULT_REGION
|
|
18
|
+
return Cmd[Session].wrap_impure(Session)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def new_resource(session: Session) -> Cmd[DynamoDBServiceResource]:
|
|
22
|
+
# boto3-stubs' resource() overload set is partially unknown because
|
|
23
|
+
# only mypy_boto3_dynamodb is installed.
|
|
24
|
+
return Cmd[DynamoDBServiceResource].wrap_impure(
|
|
25
|
+
lambda: session.resource( # pyright: ignore[reportUnknownMemberType]
|
|
26
|
+
service_name="dynamodb",
|
|
27
|
+
use_ssl=True,
|
|
28
|
+
verify=True,
|
|
29
|
+
),
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def new_client(session: Session) -> Cmd[DynamoDBClient]:
|
|
34
|
+
# boto3-stubs' client() overload set is partially unknown because
|
|
35
|
+
# only mypy_boto3_dynamodb is installed.
|
|
36
|
+
return Cmd[DynamoDBClient].wrap_impure(
|
|
37
|
+
lambda: session.client("dynamodb"), # pyright: ignore[reportUnknownMemberType]
|
|
38
|
+
)
|
|
@@ -13,6 +13,7 @@ dependencies = [
|
|
|
13
13
|
"fa-purity >=2.5.2, <3.0.0",
|
|
14
14
|
"fluidattacks-etl-utils >=5.1.0, <6.0.0",
|
|
15
15
|
"fluidattacks-utils-logger >=3.0.0, <4.0.0",
|
|
16
|
+
"mypy-boto3-dynamodb >=1.40.40, <2.0.0",
|
|
16
17
|
]
|
|
17
18
|
description = "ASM Synchronous Data Access Layer"
|
|
18
19
|
dynamic = ["version"]
|
|
@@ -33,9 +34,9 @@ dev = [
|
|
|
33
34
|
"ruff >=0.14.1, <1.0.0",
|
|
34
35
|
"botocore-stubs >=1.40.53, <2.0.0",
|
|
35
36
|
"boto3-stubs >=1.40.53, <2.0.0",
|
|
36
|
-
"
|
|
37
|
+
"basedpyright >=1.39.8, <2.0.0",
|
|
37
38
|
]
|
|
38
39
|
|
|
39
40
|
[tool.uv]
|
|
40
41
|
exclude-newer = "7 days"
|
|
41
|
-
exclude-newer-package = { fluidattacks-core = "2099-01-
|
|
42
|
+
exclude-newer-package = { fluidattacks-core = "2099-01-02T00:00:00Z", fluid-blends = "2099-01-02T00:00:00Z" , fluidattacks-utils-logger = "2099-01-02T00:00:00Z" }
|
|
@@ -8,13 +8,8 @@ from fa_purity import (
|
|
|
8
8
|
FrozenList,
|
|
9
9
|
)
|
|
10
10
|
|
|
11
|
-
from fluidattacks_integrates_dal._typing import (
|
|
12
|
-
Dict,
|
|
13
|
-
FrozenSet,
|
|
14
|
-
)
|
|
15
|
-
|
|
16
11
|
root = FullPathModule.assert_module("fluidattacks_integrates_dal")
|
|
17
|
-
_dag:
|
|
12
|
+
_dag: dict[str, FrozenList[FrozenList[str] | str]] = {
|
|
18
13
|
"fluidattacks_integrates_dal": (
|
|
19
14
|
"_cli",
|
|
20
15
|
"list_groups",
|
|
@@ -35,8 +30,8 @@ def project_dag() -> DagMap:
|
|
|
35
30
|
return item
|
|
36
31
|
|
|
37
32
|
|
|
38
|
-
def forbidden_allowlist() ->
|
|
39
|
-
_raw:
|
|
33
|
+
def forbidden_allowlist() -> dict[FullPathModule, frozenset[FullPathModule]]:
|
|
34
|
+
_raw: dict[str, frozenset[str]] = {}
|
|
40
35
|
return {
|
|
41
36
|
FullPathModule.assert_module(k): frozenset(FullPathModule.assert_module(i) for i in v)
|
|
42
37
|
for k, v in _raw.items()
|
{fluidattacks_integrates_dal-2.3.1 → fluidattacks_integrates_dal-2.3.2}/tests/arch/test_arch.py
RENAMED
|
@@ -20,7 +20,7 @@ from .arch import (
|
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
def test_dag_creation() -> None:
|
|
23
|
-
project_dag()
|
|
23
|
+
_ = project_dag()
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
def test_dag() -> None:
|
|
@@ -34,7 +34,7 @@ def test_dag_completeness() -> None:
|
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
def test_forbidden_creation() -> None:
|
|
37
|
-
forbidden_allowlist()
|
|
37
|
+
_ = forbidden_allowlist()
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
def test_forbidden() -> None:
|
{fluidattacks_integrates_dal-2.3.1 → fluidattacks_integrates_dal-2.3.2}/tests/test_list_groups.py
RENAMED
|
@@ -32,9 +32,13 @@ def test_list_groups() -> None:
|
|
|
32
32
|
)
|
|
33
33
|
mock_group = GroupId.new("foo_group").alt(Unsafe.raise_exception).to_union()
|
|
34
34
|
groups = PureIterFactory.from_list((mock_group,))
|
|
35
|
-
mock = OrgsClient(
|
|
35
|
+
mock = OrgsClient(
|
|
36
|
+
StreamFactory.from_commands(orgs.map(Cmd[OrganizationId].wrap_value)),
|
|
37
|
+
)
|
|
36
38
|
mock_2 = GroupsClient(
|
|
37
|
-
lambda _: StreamFactory.from_commands(
|
|
39
|
+
lambda _: StreamFactory.from_commands(
|
|
40
|
+
groups.map(Cmd[GroupId].wrap_value),
|
|
41
|
+
),
|
|
38
42
|
)
|
|
39
43
|
|
|
40
44
|
def check(items: FrozenList[GroupId]) -> None:
|