fluidattacks_cloudflare_sdk 0.1.0__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.
Files changed (30) hide show
  1. fluidattacks_cloudflare_sdk-0.1.0/.envrc +3 -0
  2. fluidattacks_cloudflare_sdk-0.1.0/PKG-INFO +10 -0
  3. fluidattacks_cloudflare_sdk-0.1.0/build/default.nix +13 -0
  4. fluidattacks_cloudflare_sdk-0.1.0/build/filter.nix +12 -0
  5. fluidattacks_cloudflare_sdk-0.1.0/flake.lock +353 -0
  6. fluidattacks_cloudflare_sdk-0.1.0/flake.nix +29 -0
  7. fluidattacks_cloudflare_sdk-0.1.0/fluidattacks_cloudflare_sdk/__init__.py +17 -0
  8. fluidattacks_cloudflare_sdk-0.1.0/fluidattacks_cloudflare_sdk/_client/__init__.py +19 -0
  9. fluidattacks_cloudflare_sdk-0.1.0/fluidattacks_cloudflare_sdk/_client/_client.py +30 -0
  10. fluidattacks_cloudflare_sdk-0.1.0/fluidattacks_cloudflare_sdk/_client/_core.py +23 -0
  11. fluidattacks_cloudflare_sdk-0.1.0/fluidattacks_cloudflare_sdk/_logger.py +30 -0
  12. fluidattacks_cloudflare_sdk-0.1.0/fluidattacks_cloudflare_sdk/ai_gateway/__init__.py +56 -0
  13. fluidattacks_cloudflare_sdk-0.1.0/fluidattacks_cloudflare_sdk/ai_gateway/_client.py +69 -0
  14. fluidattacks_cloudflare_sdk-0.1.0/fluidattacks_cloudflare_sdk/ai_gateway/_decode.py +38 -0
  15. fluidattacks_cloudflare_sdk-0.1.0/fluidattacks_cloudflare_sdk/ai_gateway/core.py +98 -0
  16. fluidattacks_cloudflare_sdk-0.1.0/fluidattacks_cloudflare_sdk/core.py +19 -0
  17. fluidattacks_cloudflare_sdk-0.1.0/mypy.ini +30 -0
  18. fluidattacks_cloudflare_sdk-0.1.0/pyproject.toml +25 -0
  19. fluidattacks_cloudflare_sdk-0.1.0/ruff.toml +40 -0
  20. fluidattacks_cloudflare_sdk-0.1.0/tests/__init__.py +0 -0
  21. fluidattacks_cloudflare_sdk-0.1.0/tests/ai_gateway/__init__.py +0 -0
  22. fluidattacks_cloudflare_sdk-0.1.0/tests/ai_gateway/test_decode.py +136 -0
  23. fluidattacks_cloudflare_sdk-0.1.0/tests/arch/__init__.py +0 -0
  24. fluidattacks_cloudflare_sdk-0.1.0/tests/arch/arch.py +44 -0
  25. fluidattacks_cloudflare_sdk-0.1.0/tests/arch/test_arch.py +32 -0
  26. fluidattacks_cloudflare_sdk-0.1.0/tests_fx/__init__.py +0 -0
  27. fluidattacks_cloudflare_sdk-0.1.0/tests_fx/_utils.py +60 -0
  28. fluidattacks_cloudflare_sdk-0.1.0/tests_fx/ai_gateway/__init__.py +0 -0
  29. fluidattacks_cloudflare_sdk-0.1.0/tests_fx/ai_gateway/test_client.py +44 -0
  30. fluidattacks_cloudflare_sdk-0.1.0/uv.lock +1800 -0
@@ -0,0 +1,3 @@
1
+ # use https://github.com/nix-community/nix-direnv
2
+ ln -f ../../common/mypy.ini ./mypy.ini
3
+ use_flake ".#python311.devShell"
@@ -0,0 +1,10 @@
1
+ Metadata-Version: 2.4
2
+ Name: fluidattacks_cloudflare_sdk
3
+ Version: 0.1.0
4
+ Summary: cloudflare SDK
5
+ Author-email: Product Team <development@fluidattacks.com>
6
+ Requires-Python: >=3.11
7
+ Requires-Dist: cloudflare >=4.0.0, <5.0.0
8
+ Requires-Dist: fa-purity >=2.5.0, <3.0.0
9
+ Requires-Dist: fluidattacks-etl-utils >=4.0.0, <5.0.0
10
+ Requires-Dist: fluidattacks-utils-logger >=3.0.0, <4.0.0
@@ -0,0 +1,13 @@
1
+ {
2
+ nixpkgs,
3
+ builders,
4
+ scripts,
5
+ src,
6
+ }:
7
+ {
8
+ inherit src;
9
+ root_path = "observes/sdk/cloudflare";
10
+ module_name = "fluidattacks_cloudflare_sdk";
11
+ pypi_token_var = "CLOUDFLARE_SDK_TOKEN";
12
+ override = b: b;
13
+ }
@@ -0,0 +1,12 @@
1
+ path_filter: src:
2
+ path_filter {
3
+ root = src;
4
+ include = [
5
+ "fluidattacks_cloudflare_sdk"
6
+ "tests"
7
+ "pyproject.toml"
8
+ "mypy.ini"
9
+ "ruff.toml"
10
+ "uv.lock"
11
+ ];
12
+ }
@@ -0,0 +1,353 @@
1
+ {
2
+ "nodes": {
3
+ "flake-parts": {
4
+ "inputs": {
5
+ "nixpkgs-lib": "nixpkgs-lib"
6
+ },
7
+ "locked": {
8
+ "lastModified": 1762810396,
9
+ "narHash": "sha256-dxFVgQPG+R72dkhXTtqUm7KpxElw3u6E+YlQ2WaDgt8=",
10
+ "owner": "hercules-ci",
11
+ "repo": "flake-parts",
12
+ "rev": "0bdadb1b265fb4143a75bd1ec7d8c915898a9923",
13
+ "type": "github"
14
+ },
15
+ "original": {
16
+ "owner": "hercules-ci",
17
+ "repo": "flake-parts",
18
+ "type": "github"
19
+ }
20
+ },
21
+ "nix_filter": {
22
+ "locked": {
23
+ "lastModified": 1757882181,
24
+ "narHash": "sha256-+cCxYIh2UNalTz364p+QYmWHs0P+6wDhiWR4jDIKQIU=",
25
+ "owner": "numtide",
26
+ "repo": "nix-filter",
27
+ "rev": "59c44d1909c72441144b93cf0f054be7fe764de5",
28
+ "type": "github"
29
+ },
30
+ "original": {
31
+ "owner": "numtide",
32
+ "repo": "nix-filter",
33
+ "type": "github"
34
+ }
35
+ },
36
+ "nix_filter_2": {
37
+ "locked": {
38
+ "lastModified": 1731533336,
39
+ "narHash": "sha256-oRam5PS1vcrr5UPgALW0eo1m/5/pls27Z/pabHNy2Ms=",
40
+ "owner": "numtide",
41
+ "repo": "nix-filter",
42
+ "rev": "f7653272fd234696ae94229839a99b73c9ab7de0",
43
+ "type": "github"
44
+ },
45
+ "original": {
46
+ "owner": "numtide",
47
+ "repo": "nix-filter",
48
+ "type": "github"
49
+ }
50
+ },
51
+ "nixpkgs": {
52
+ "locked": {
53
+ "lastModified": 1736441877,
54
+ "narHash": "sha256-m3+PhBFkDwqo9lBplG4AyMW8P4/KcioJRS1UG8N7okM=",
55
+ "owner": "nixos",
56
+ "repo": "nixpkgs",
57
+ "rev": "ce3899414dab3297cf025bfa356dc2da426feefd",
58
+ "type": "github"
59
+ },
60
+ "original": {
61
+ "owner": "nixos",
62
+ "repo": "nixpkgs",
63
+ "type": "github"
64
+ }
65
+ },
66
+ "nixpkgs-lib": {
67
+ "locked": {
68
+ "lastModified": 1761765539,
69
+ "narHash": "sha256-b0yj6kfvO8ApcSE+QmA6mUfu8IYG6/uU28OFn4PaC8M=",
70
+ "owner": "nix-community",
71
+ "repo": "nixpkgs.lib",
72
+ "rev": "719359f4562934ae99f5443f20aa06c2ffff91fc",
73
+ "type": "github"
74
+ },
75
+ "original": {
76
+ "owner": "nix-community",
77
+ "repo": "nixpkgs.lib",
78
+ "type": "github"
79
+ }
80
+ },
81
+ "nixpkgs_2": {
82
+ "locked": {
83
+ "lastModified": 1758690382,
84
+ "narHash": "sha256-NY3kSorgqE5LMm1LqNwGne3ZLMF2/ILgLpFr1fS4X3o=",
85
+ "owner": "nixos",
86
+ "repo": "nixpkgs",
87
+ "rev": "e643668fd71b949c53f8626614b21ff71a07379d",
88
+ "type": "github"
89
+ },
90
+ "original": {
91
+ "owner": "nixos",
92
+ "ref": "nixos-unstable",
93
+ "repo": "nixpkgs",
94
+ "type": "github"
95
+ }
96
+ },
97
+ "nixpkgs_3": {
98
+ "locked": {
99
+ "lastModified": 1758690382,
100
+ "narHash": "sha256-NY3kSorgqE5LMm1LqNwGne3ZLMF2/ILgLpFr1fS4X3o=",
101
+ "owner": "nixos",
102
+ "repo": "nixpkgs",
103
+ "rev": "e643668fd71b949c53f8626614b21ff71a07379d",
104
+ "type": "github"
105
+ },
106
+ "original": {
107
+ "owner": "nixos",
108
+ "ref": "nixos-unstable",
109
+ "repo": "nixpkgs",
110
+ "type": "github"
111
+ }
112
+ },
113
+ "nixpkgs_4": {
114
+ "locked": {
115
+ "lastModified": 1761373498,
116
+ "narHash": "sha256-Q/uhWNvd7V7k1H1ZPMy/vkx3F8C13ZcdrKjO7Jv7v0c=",
117
+ "owner": "nixos",
118
+ "repo": "nixpkgs",
119
+ "rev": "6a08e6bb4e46ff7fcbb53d409b253f6bad8a28ce",
120
+ "type": "github"
121
+ },
122
+ "original": {
123
+ "owner": "nixos",
124
+ "ref": "nixos-unstable",
125
+ "repo": "nixpkgs",
126
+ "type": "github"
127
+ }
128
+ },
129
+ "nixpkgs_flake": {
130
+ "locked": {
131
+ "lastModified": 1762812764,
132
+ "narHash": "sha256-MNqrovkO8AEQeYQK7e3X2GDx2H8vfDIxV4K/VEaIjjo=",
133
+ "owner": "nixos",
134
+ "repo": "nixpkgs",
135
+ "rev": "400156fe527ab6b54cf6f70cca2c8385548a29c4",
136
+ "type": "github"
137
+ },
138
+ "original": {
139
+ "owner": "nixos",
140
+ "repo": "nixpkgs",
141
+ "type": "github"
142
+ }
143
+ },
144
+ "observes_flake_builder": {
145
+ "inputs": {
146
+ "nix_filter": "nix_filter",
147
+ "nixpkgs_flake": "nixpkgs_flake",
148
+ "pynix_flake": "pynix_flake",
149
+ "pyproject-build-systems": "pyproject-build-systems",
150
+ "pyproject-nix": "pyproject-nix_2",
151
+ "shell-helpers": "shell-helpers",
152
+ "uv2nix": "uv2nix_2"
153
+ },
154
+ "locked": {
155
+ "dir": "observes/common/std_flake_2",
156
+ "lastModified": 1764767408,
157
+ "narHash": "sha256-CYGyCtQuboXbHQ0OUXNNdXXIcPOM1ZhOM94LUNjEQig=",
158
+ "ref": "refs/heads/trunk",
159
+ "rev": "28bda83eeda56c9c4016f43c86aaf93a366446c3",
160
+ "shallow": true,
161
+ "type": "git",
162
+ "url": "ssh://git@gitlab.com/fluidattacks/universe"
163
+ },
164
+ "original": {
165
+ "dir": "observes/common/std_flake_2",
166
+ "rev": "28bda83eeda56c9c4016f43c86aaf93a366446c3",
167
+ "shallow": true,
168
+ "type": "git",
169
+ "url": "ssh://git@gitlab.com/fluidattacks/universe"
170
+ }
171
+ },
172
+ "pynix_flake": {
173
+ "inputs": {
174
+ "nix_filter": "nix_filter_2",
175
+ "nixpkgs": "nixpkgs"
176
+ },
177
+ "locked": {
178
+ "lastModified": 1758642502,
179
+ "narHash": "sha256-PD/bQMz2dqZSkydHyvRh+jS/0qoV8SdcIVs6sassteQ=",
180
+ "owner": "dmurciaatfluid",
181
+ "repo": "python_nix_builder",
182
+ "rev": "809aafe2e1995e72c15378d099bf251b78f04a20",
183
+ "type": "gitlab"
184
+ },
185
+ "original": {
186
+ "owner": "dmurciaatfluid",
187
+ "repo": "python_nix_builder",
188
+ "type": "gitlab"
189
+ }
190
+ },
191
+ "pyproject-build-systems": {
192
+ "inputs": {
193
+ "nixpkgs": "nixpkgs_2",
194
+ "pyproject-nix": "pyproject-nix",
195
+ "uv2nix": "uv2nix"
196
+ },
197
+ "locked": {
198
+ "lastModified": 1761781027,
199
+ "narHash": "sha256-YDvxPAm2WnxrznRqWwHLjryBGG5Ey1ATEJXrON+TWt8=",
200
+ "owner": "pyproject-nix",
201
+ "repo": "build-system-pkgs",
202
+ "rev": "795a980d25301e5133eca37adae37283ec3c8e66",
203
+ "type": "github"
204
+ },
205
+ "original": {
206
+ "owner": "pyproject-nix",
207
+ "repo": "build-system-pkgs",
208
+ "type": "github"
209
+ }
210
+ },
211
+ "pyproject-nix": {
212
+ "inputs": {
213
+ "nixpkgs": [
214
+ "observes_flake_builder",
215
+ "pyproject-build-systems",
216
+ "nixpkgs"
217
+ ]
218
+ },
219
+ "locked": {
220
+ "lastModified": 1758265079,
221
+ "narHash": "sha256-amLaLNwKSZPShQHzfgmc/9o76dU8xzN0743dWgvYlr8=",
222
+ "owner": "nix-community",
223
+ "repo": "pyproject.nix",
224
+ "rev": "02e9418fd4af638447dca4b17b1280da95527fc9",
225
+ "type": "github"
226
+ },
227
+ "original": {
228
+ "owner": "nix-community",
229
+ "repo": "pyproject.nix",
230
+ "type": "github"
231
+ }
232
+ },
233
+ "pyproject-nix_2": {
234
+ "inputs": {
235
+ "nixpkgs": "nixpkgs_3"
236
+ },
237
+ "locked": {
238
+ "lastModified": 1762427963,
239
+ "narHash": "sha256-CkPlAbIQ87wmjy5qHibfzk4DmMGBNqFer+lLfXjpP5M=",
240
+ "owner": "pyproject-nix",
241
+ "repo": "pyproject.nix",
242
+ "rev": "4540ea004e04fcd12dd2738d51383d10f956f7b9",
243
+ "type": "github"
244
+ },
245
+ "original": {
246
+ "owner": "pyproject-nix",
247
+ "repo": "pyproject.nix",
248
+ "type": "github"
249
+ }
250
+ },
251
+ "pyproject-nix_3": {
252
+ "inputs": {
253
+ "nixpkgs": [
254
+ "observes_flake_builder",
255
+ "uv2nix",
256
+ "nixpkgs"
257
+ ]
258
+ },
259
+ "locked": {
260
+ "lastModified": 1760402624,
261
+ "narHash": "sha256-jF6UKLs2uGc2rtved8Vrt58oTWjTQoAssuYs/0578Z4=",
262
+ "owner": "pyproject-nix",
263
+ "repo": "pyproject.nix",
264
+ "rev": "84c4ea102127c77058ea1ed7be7300261fafc7d2",
265
+ "type": "github"
266
+ },
267
+ "original": {
268
+ "owner": "pyproject-nix",
269
+ "repo": "pyproject.nix",
270
+ "type": "github"
271
+ }
272
+ },
273
+ "root": {
274
+ "inputs": {
275
+ "observes_flake_builder": "observes_flake_builder"
276
+ }
277
+ },
278
+ "shell-helpers": {
279
+ "inputs": {
280
+ "flake-parts": "flake-parts",
281
+ "nixpkgs": [
282
+ "observes_flake_builder",
283
+ "nixpkgs_flake"
284
+ ]
285
+ },
286
+ "locked": {
287
+ "dir": "common/utils/shell-helpers",
288
+ "lastModified": 1762806066,
289
+ "narHash": "sha256-Wz99Fl7SpPU1NkTHJ36XOo6DjOEAMXCw3ThRABOS2Hs=",
290
+ "ref": "refs/heads/trunk",
291
+ "rev": "d73cfdc7ae9e7f547e22a4481d4c2ccce38b26a8",
292
+ "shallow": true,
293
+ "type": "git",
294
+ "url": "ssh://git@gitlab.com/fluidattacks/universe"
295
+ },
296
+ "original": {
297
+ "dir": "common/utils/shell-helpers",
298
+ "rev": "d73cfdc7ae9e7f547e22a4481d4c2ccce38b26a8",
299
+ "shallow": true,
300
+ "type": "git",
301
+ "url": "ssh://git@gitlab.com/fluidattacks/universe"
302
+ }
303
+ },
304
+ "uv2nix": {
305
+ "inputs": {
306
+ "nixpkgs": [
307
+ "observes_flake_builder",
308
+ "pyproject-build-systems",
309
+ "nixpkgs"
310
+ ],
311
+ "pyproject-nix": [
312
+ "observes_flake_builder",
313
+ "pyproject-build-systems",
314
+ "pyproject-nix"
315
+ ]
316
+ },
317
+ "locked": {
318
+ "lastModified": 1758933732,
319
+ "narHash": "sha256-HAmm1GBS1myZCFuog0DC2ZLaynvZtiUI2Crmo+cdQI0=",
320
+ "owner": "pyproject-nix",
321
+ "repo": "uv2nix",
322
+ "rev": "273ce18f913d8559e0d04f820d724308966d7c4d",
323
+ "type": "github"
324
+ },
325
+ "original": {
326
+ "owner": "pyproject-nix",
327
+ "repo": "uv2nix",
328
+ "type": "github"
329
+ }
330
+ },
331
+ "uv2nix_2": {
332
+ "inputs": {
333
+ "nixpkgs": "nixpkgs_4",
334
+ "pyproject-nix": "pyproject-nix_3"
335
+ },
336
+ "locked": {
337
+ "lastModified": 1761872265,
338
+ "narHash": "sha256-i25GRgp2vUOebY70L3NTAgkd+Pr1hnn5xM3qHxH0ONU=",
339
+ "owner": "pyproject-nix",
340
+ "repo": "uv2nix",
341
+ "rev": "74dfb62871be152ad3673b143b0cc56105a4f3c5",
342
+ "type": "github"
343
+ },
344
+ "original": {
345
+ "owner": "pyproject-nix",
346
+ "repo": "uv2nix",
347
+ "type": "github"
348
+ }
349
+ }
350
+ },
351
+ "root": "root",
352
+ "version": 7
353
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ description = "Cloudflare API SDK";
3
+
4
+ inputs = {
5
+ observes_flake_builder = {
6
+ url = "git+ssh://git@gitlab.com/fluidattacks/universe?shallow=1&rev=28bda83eeda56c9c4016f43c86aaf93a366446c3&dir=observes/common/std_flake_2";
7
+ };
8
+ };
9
+
10
+ outputs =
11
+ { self, ... }@inputs:
12
+ let
13
+ build_args =
14
+ {
15
+ system,
16
+ python_version,
17
+ nixpkgs,
18
+ builders,
19
+ scripts,
20
+ }:
21
+ import ./build {
22
+ inherit nixpkgs builders scripts;
23
+ src = import ./build/filter.nix nixpkgs.nix-filter self;
24
+ };
25
+ in
26
+ {
27
+ packages = inputs.observes_flake_builder.outputs.build build_args;
28
+ };
29
+ }
@@ -0,0 +1,17 @@
1
+ """Cloudflare SDK for fluidattacks observes."""
2
+
3
+ from fa_purity import Unsafe
4
+
5
+ from fluidattacks_cloudflare_sdk._client import Token
6
+ from fluidattacks_cloudflare_sdk._logger import set_logger
7
+ from fluidattacks_cloudflare_sdk.core import AccountId, GatewayId
8
+
9
+ __version__ = "0.1.0"
10
+
11
+ Unsafe.compute(set_logger(__name__, __version__))
12
+
13
+ __all__ = [
14
+ "AccountId",
15
+ "GatewayId",
16
+ "Token",
17
+ ]
@@ -0,0 +1,19 @@
1
+ """Private connection package for the Cloudflare SDK."""
2
+
3
+ from dataclasses import dataclass
4
+
5
+ from fluidattacks_cloudflare_sdk._client._client import CloudflareClient
6
+ from fluidattacks_cloudflare_sdk._client._core import Client, Token
7
+
8
+
9
+ @dataclass(frozen=True)
10
+ class CloudflareClientFactory:
11
+ """Factory for a Cloudflare Client."""
12
+
13
+ @staticmethod
14
+ def new(token: Token) -> Client:
15
+ """Build a Client from a Token."""
16
+ return CloudflareClient.new(token).client
17
+
18
+
19
+ __all__ = ["Client", "CloudflareClientFactory", "Token"]
@@ -0,0 +1,30 @@
1
+ """Private Cloudflare client; builds the public Client."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from typing import TYPE_CHECKING
7
+
8
+ from cloudflare import Cloudflare
9
+
10
+ from fluidattacks_cloudflare_sdk._client._core import Client
11
+
12
+ if TYPE_CHECKING:
13
+ from fluidattacks_cloudflare_sdk._client._core import Token
14
+
15
+
16
+ @dataclass(frozen=True)
17
+ class CloudflareClient:
18
+ """Private class holding the raw Cloudflare connection."""
19
+
20
+ _cloudflare: Cloudflare
21
+
22
+ @staticmethod
23
+ def new(token: Token) -> CloudflareClient:
24
+ """Build a CloudflareClient from a Token."""
25
+ return CloudflareClient(Cloudflare(api_token=token.raw))
26
+
27
+ @property
28
+ def client(self) -> Client:
29
+ """Return the opaque Client."""
30
+ return Client(self._cloudflare)
@@ -0,0 +1,23 @@
1
+ """Core types for the private Cloudflare connection package."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from typing import TYPE_CHECKING
7
+
8
+ if TYPE_CHECKING:
9
+ from cloudflare import Cloudflare
10
+
11
+
12
+ @dataclass(frozen=True)
13
+ class Token:
14
+ """Cloudflare API token."""
15
+
16
+ raw: str
17
+
18
+
19
+ @dataclass(frozen=True)
20
+ class Client:
21
+ """Opaque Cloudflare connection; raw field is SDK-internal."""
22
+
23
+ client: Cloudflare
@@ -0,0 +1,30 @@
1
+ """Logger configuration for the Cloudflare SDK."""
2
+
3
+ from fa_purity import (
4
+ Cmd,
5
+ )
6
+ from fluidattacks_utils_logger import (
7
+ set_main_log,
8
+ )
9
+ from fluidattacks_utils_logger.env import (
10
+ current_app_env,
11
+ observes_debug,
12
+ )
13
+ from fluidattacks_utils_logger.handlers import (
14
+ LoggingConf,
15
+ )
16
+
17
+
18
+ def set_logger(root_name: str, version: str) -> Cmd[None]:
19
+ """Configure structured logging for the SDK."""
20
+ app_env = current_app_env()
21
+ debug = observes_debug()
22
+ conf = app_env.map(
23
+ lambda env: LoggingConf(
24
+ app_name="observes_cloudflare",
25
+ app_type="sdk",
26
+ app_version=version,
27
+ release_stage=env,
28
+ ),
29
+ )
30
+ return debug.bind(lambda d: conf.bind(lambda c: set_main_log(root_name, c, d)))
@@ -0,0 +1,56 @@
1
+ """AI Gateway sub-package for the Cloudflare SDK."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from typing import TYPE_CHECKING
7
+
8
+ from fluidattacks_cloudflare_sdk._client import CloudflareClientFactory
9
+ from fluidattacks_cloudflare_sdk.ai_gateway._client import list_logs
10
+ from fluidattacks_cloudflare_sdk.ai_gateway.core import (
11
+ AiGatewayClient,
12
+ EndDate,
13
+ LogRecord,
14
+ LogsOrderBy,
15
+ LogsQuery,
16
+ StartDate,
17
+ )
18
+
19
+ if TYPE_CHECKING:
20
+ from fluidattacks_cloudflare_sdk._client import Client, Token
21
+ from fluidattacks_cloudflare_sdk.core import AccountId, GatewayId
22
+
23
+
24
+ def _from_client(
25
+ cloudflare: Client,
26
+ account_id: AccountId,
27
+ gateway_id: GatewayId,
28
+ ) -> AiGatewayClient:
29
+ return AiGatewayClient(
30
+ list_logs=lambda q: list_logs(cloudflare, account_id, gateway_id, q),
31
+ )
32
+
33
+
34
+ @dataclass(frozen=True)
35
+ class AiGatewayClientFactory:
36
+ """Factory for AiGatewayClient."""
37
+
38
+ @staticmethod
39
+ def new(
40
+ token: Token,
41
+ account_id: AccountId,
42
+ gateway_id: GatewayId,
43
+ ) -> AiGatewayClient:
44
+ """Build an AiGatewayClient from a token and identifiers."""
45
+ return _from_client(CloudflareClientFactory.new(token), account_id, gateway_id)
46
+
47
+
48
+ __all__ = [
49
+ "AiGatewayClient",
50
+ "AiGatewayClientFactory",
51
+ "EndDate",
52
+ "LogRecord",
53
+ "LogsOrderBy",
54
+ "LogsQuery",
55
+ "StartDate",
56
+ ]
@@ -0,0 +1,69 @@
1
+ from __future__ import annotations
2
+
3
+ import logging
4
+ from typing import TYPE_CHECKING
5
+
6
+ from cloudflare import NOT_GIVEN
7
+ from fa_purity import Cmd, FrozenList, Result, ResultE, Unsafe, cast_exception
8
+
9
+ from fluidattacks_cloudflare_sdk.ai_gateway._decode import decode_log
10
+ from fluidattacks_cloudflare_sdk.ai_gateway.core import (
11
+ LogRecord,
12
+ LogsOrderBy,
13
+ LogsQuery,
14
+ )
15
+
16
+ if TYPE_CHECKING:
17
+ from fluidattacks_cloudflare_sdk._client import Client
18
+ from fluidattacks_cloudflare_sdk.core import AccountId, GatewayId
19
+
20
+ LOG = logging.getLogger(__name__)
21
+
22
+
23
+ def list_logs(
24
+ cloudflare: Client,
25
+ account_id: AccountId,
26
+ gateway_id: GatewayId,
27
+ query: LogsQuery,
28
+ ) -> Cmd[ResultE[FrozenList[LogRecord]]]:
29
+ _order = query.order_by.value_or(LogsOrderBy.default())
30
+ _start = query.start.map(lambda s: s.raw.date_time.strftime("%Y-%m-%dT%H:%M:%SZ")).value_or(
31
+ NOT_GIVEN
32
+ )
33
+ _end = query.end.map(lambda e: e.raw.date_time.strftime("%Y-%m-%dT%H:%M:%SZ")).value_or(
34
+ NOT_GIVEN
35
+ )
36
+
37
+ def _action() -> ResultE[FrozenList[LogRecord]]:
38
+ try:
39
+ LOG.info("fetching ai gateway logs for gateway %s", gateway_id.raw)
40
+ first_page = cloudflare.client.ai_gateway.logs.list(
41
+ gateway_id.raw,
42
+ account_id=account_id.raw,
43
+ start_date=_start,
44
+ end_date=_end,
45
+ order_by=_order.field,
46
+ order_by_direction=_order.direction,
47
+ )
48
+ items: list[LogRecord] = []
49
+ for page in first_page.iter_pages():
50
+ page_records = page.result
51
+ items.extend(
52
+ decode_log(raw).alt(Unsafe.raise_exception).to_union() for raw in page_records
53
+ )
54
+ LOG.info(
55
+ "page fetched: %d records (%d total so far)",
56
+ len(page_records),
57
+ len(items),
58
+ )
59
+ LOG.info(
60
+ "finished: %d log records from gateway %s",
61
+ len(items),
62
+ gateway_id.raw,
63
+ )
64
+ return Result.success(tuple(items))
65
+ except Exception as err:
66
+ LOG.exception("failed to fetch ai gateway logs")
67
+ return Result.failure(err, FrozenList[LogRecord]).alt(cast_exception)
68
+
69
+ return Cmd.wrap_impure(_action)