fluidattacks_gitlab_sdk 4.0.0__tar.gz → 6.0.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 (98) hide show
  1. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/PKG-INFO +3 -3
  2. fluidattacks_gitlab_sdk-6.0.0/build/default.nix +13 -0
  3. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/flake.lock +50 -96
  4. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/flake.nix +5 -4
  5. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/__init__.py +1 -1
  6. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/_decoders.py +12 -13
  7. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/_gql_client/_client.py +13 -9
  8. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/_gql_client/_handlers.py +5 -5
  9. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/_handlers.py +7 -10
  10. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/_http_client/_client_1.py +57 -19
  11. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/_http_client/_core.py +27 -13
  12. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/ids.py +4 -2
  13. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/issues/_client/__init__.py +4 -2
  14. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/issues/_client/_decode.py +3 -3
  15. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/issues/_client/_get_issue.py +14 -5
  16. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/issues/_client/_most_recent.py +24 -10
  17. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/issues/_client/_updated_by.py +12 -12
  18. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/issues/core.py +8 -5
  19. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/jobs/_client.py +8 -5
  20. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/jobs/_decode.py +11 -5
  21. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/jobs/core.py +9 -5
  22. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/members/_client.py +13 -2
  23. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/members/_decode.py +3 -1
  24. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/members/core.py +6 -3
  25. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/merge_requests/_client.py +27 -14
  26. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/merge_requests/_decode.py +8 -4
  27. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/merge_requests/core.py +9 -6
  28. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/milestones/_client.py +25 -11
  29. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/milestones/_decode.py +5 -3
  30. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/milestones/core.py +8 -5
  31. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/mr_approvals/_client.py +4 -1
  32. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/mr_approvals/_decode.py +10 -6
  33. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/mr_approvals/core.py +8 -3
  34. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/mr_notes/_client.py +7 -2
  35. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/mr_notes/_core.py +7 -4
  36. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/mr_notes/_decode.py +1 -1
  37. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/users/core.py +4 -2
  38. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/pyproject.toml +5 -4
  39. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/ruff.toml +17 -11
  40. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests/arch/arch.py +3 -5
  41. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests/arch/test_arch.py +2 -2
  42. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests/issues/test_decode.py +20 -16
  43. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests/jobs/test_decode_job.py +10 -10
  44. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests/merge_request/test_decode.py +56 -43
  45. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests/mr_approvals/data.json +4 -2
  46. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests/mr_approvals/decoder_test.py +12 -2
  47. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests/mr_notes/decoder_test.py +4 -7
  48. fluidattacks_gitlab_sdk-6.0.0/uv.lock +975 -0
  49. fluidattacks_gitlab_sdk-4.0.0/build/default.nix +0 -13
  50. fluidattacks_gitlab_sdk-4.0.0/uv.lock +0 -1525
  51. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/.envrc +0 -0
  52. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/build/filter.nix +0 -0
  53. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/_gql_client/__init__.py +0 -0
  54. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/_gql_client/_error.py +0 -0
  55. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/_http_client/__init__.py +0 -0
  56. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/_logger.py +0 -0
  57. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/issues/__init__.py +0 -0
  58. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/jobs/__init__.py +0 -0
  59. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/members/__init__.py +0 -0
  60. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/merge_requests/__init__.py +0 -0
  61. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/milestones/__init__.py +0 -0
  62. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/mr_approvals/__init__.py +0 -0
  63. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/mr_notes/__init__.py +0 -0
  64. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/py.typed +0 -0
  65. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/users/__init__.py +0 -0
  66. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/fluidattacks_gitlab_sdk/users/decode.py +0 -0
  67. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/mypy.ini +0 -0
  68. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests/__init__.py +0 -0
  69. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests/arch/__init__.py +0 -0
  70. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests/issues/__init__.py +0 -0
  71. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests/issues/data.json +0 -0
  72. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests/jobs/__init__.py +0 -0
  73. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests/jobs/data.json +0 -0
  74. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests/members/__init__.py +0 -0
  75. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests/members/data.json +0 -0
  76. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests/members/test_decode_members.py +0 -0
  77. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests/merge_request/__init__.py +0 -0
  78. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests/merge_request/data.json +0 -0
  79. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests/merge_request/data_mr_updates.json +0 -0
  80. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests/mr_approvals/__init__.py +0 -0
  81. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests/mr_notes/__init__.py +0 -0
  82. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests/mr_notes/data.json +0 -0
  83. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests/py.typed +0 -0
  84. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests_fx/__init__.py +0 -0
  85. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests_fx/_utils.py +0 -0
  86. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests_fx/issues/__init__.py +0 -0
  87. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests_fx/issues/test_issue_client.py +0 -0
  88. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests_fx/jobs/__init__.py +0 -0
  89. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests_fx/jobs/client_test.py +0 -0
  90. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests_fx/members/__init__.py +0 -0
  91. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests_fx/members/test_client_members.py +0 -0
  92. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests_fx/milestones/__init__.py +0 -0
  93. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests_fx/milestones/client_test.py +0 -0
  94. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests_fx/mr_approvals/__init__.py +0 -0
  95. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests_fx/mr_approvals/client_test.py +0 -0
  96. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests_fx/py.typed +0 -0
  97. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests_fx/test_gql_client.py +0 -0
  98. {fluidattacks_gitlab_sdk-4.0.0 → fluidattacks_gitlab_sdk-6.0.0}/tests_fx/test_mr.py +0 -0
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fluidattacks_gitlab_sdk
3
- Version: 4.0.0
3
+ Version: 6.0.0
4
4
  Summary: gitlab SDK
5
5
  Author-email: Product Team <development@fluidattacks.com>
6
- Requires-Python: >=3.11
6
+ Requires-Python: >=3.13.14, <3.14
7
7
  Requires-Dist: gql >=3.5.0, <4.0.0
8
8
  Requires-Dist: requests-toolbelt >=1.0.0, <2.0.0
9
9
  Requires-Dist: fa-purity >=2.5.2, <3.0.0
10
10
  Requires-Dist: pure-requests >=3.0.0, <4.0.0
11
11
  Requires-Dist: python-dateutil >=2.8.0, <3.0.0
12
12
  Requires-Dist: fluidattacks-etl-utils >=4.0.0, <5.1.1
13
- Requires-Dist: fluidattacks-utils-logger >=3.0.2, <4.0.0
13
+ Requires-Dist: fluidattacks-utils-logger >=3.0.5, <4.0.0
@@ -0,0 +1,13 @@
1
+ { src }:
2
+ {
3
+ inherit src;
4
+ root_path = "observes/sdk/gitlab";
5
+ module_name = "fluidattacks_gitlab_sdk";
6
+ pypi_token = {
7
+ method = "oidc";
8
+ };
9
+ override.checks = {
10
+ deptry = false;
11
+ import_linter = false;
12
+ };
13
+ }
@@ -5,11 +5,11 @@
5
5
  "nixpkgs-lib": "nixpkgs-lib"
6
6
  },
7
7
  "locked": {
8
- "lastModified": 1762810396,
9
- "narHash": "sha256-dxFVgQPG+R72dkhXTtqUm7KpxElw3u6E+YlQ2WaDgt8=",
8
+ "lastModified": 1768135262,
9
+ "narHash": "sha256-PVvu7OqHBGWN16zSi6tEmPwwHQ4rLPU9Plvs8/1TUBY=",
10
10
  "owner": "hercules-ci",
11
11
  "repo": "flake-parts",
12
- "rev": "0bdadb1b265fb4143a75bd1ec7d8c915898a9923",
12
+ "rev": "80daad04eddbbf5a4d883996a73f3f542fa437ac",
13
13
  "type": "github"
14
14
  },
15
15
  "original": {
@@ -33,43 +33,29 @@
33
33
  "type": "github"
34
34
  }
35
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
36
  "nixpkgs": {
52
37
  "locked": {
53
- "lastModified": 1736441877,
54
- "narHash": "sha256-m3+PhBFkDwqo9lBplG4AyMW8P4/KcioJRS1UG8N7okM=",
38
+ "lastModified": 1785133411,
39
+ "narHash": "sha256-Yjv0WEg39KRYS0rBdTbu6Fc/or/ihAKk13W9sQ6VWd0=",
55
40
  "owner": "nixos",
56
41
  "repo": "nixpkgs",
57
- "rev": "ce3899414dab3297cf025bfa356dc2da426feefd",
42
+ "rev": "2f5a153c270b70cb0f8c11f46d96d6d3bc39f4e3",
58
43
  "type": "github"
59
44
  },
60
45
  "original": {
61
46
  "owner": "nixos",
62
47
  "repo": "nixpkgs",
48
+ "rev": "2f5a153c270b70cb0f8c11f46d96d6d3bc39f4e3",
63
49
  "type": "github"
64
50
  }
65
51
  },
66
52
  "nixpkgs-lib": {
67
53
  "locked": {
68
- "lastModified": 1761765539,
69
- "narHash": "sha256-b0yj6kfvO8ApcSE+QmA6mUfu8IYG6/uU28OFn4PaC8M=",
54
+ "lastModified": 1765674936,
55
+ "narHash": "sha256-k00uTP4JNfmejrCLJOwdObYC9jHRrr/5M/a/8L2EIdo=",
70
56
  "owner": "nix-community",
71
57
  "repo": "nixpkgs.lib",
72
- "rev": "719359f4562934ae99f5443f20aa06c2ffff91fc",
58
+ "rev": "2075416fcb47225d9b68ac469a5c4801a9c4dd85",
73
59
  "type": "github"
74
60
  },
75
61
  "original": {
@@ -126,68 +112,6 @@
126
112
  "type": "github"
127
113
  }
128
114
  },
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
115
  "pyproject-build-systems": {
192
116
  "inputs": {
193
117
  "nixpkgs": "nixpkgs_2",
@@ -211,7 +135,7 @@
211
135
  "pyproject-nix": {
212
136
  "inputs": {
213
137
  "nixpkgs": [
214
- "observes_flake_builder",
138
+ "python_builder",
215
139
  "pyproject-build-systems",
216
140
  "nixpkgs"
217
141
  ]
@@ -251,7 +175,7 @@
251
175
  "pyproject-nix_3": {
252
176
  "inputs": {
253
177
  "nixpkgs": [
254
- "observes_flake_builder",
178
+ "python_builder",
255
179
  "uv2nix",
256
180
  "nixpkgs"
257
181
  ]
@@ -270,32 +194,62 @@
270
194
  "type": "github"
271
195
  }
272
196
  },
197
+ "python_builder": {
198
+ "inputs": {
199
+ "nix_filter": "nix_filter",
200
+ "nixpkgs_flake": [
201
+ "nixpkgs"
202
+ ],
203
+ "pyproject-build-systems": "pyproject-build-systems",
204
+ "pyproject-nix": "pyproject-nix_2",
205
+ "shell-helpers": "shell-helpers",
206
+ "uv2nix": "uv2nix_2"
207
+ },
208
+ "locked": {
209
+ "dir": "common/utils/python-builder",
210
+ "lastModified": 1787753967,
211
+ "narHash": "sha256-1kWAiANGMA4B9flxHFj73EwvOpF8r0nXGg1RVXNKPK8=",
212
+ "ref": "refs/heads/trunk",
213
+ "rev": "2490a24f91f075f7580cd0b9df5bc01dbc467a50",
214
+ "shallow": true,
215
+ "type": "git",
216
+ "url": "ssh://git@gitlab.com/fluidattacks/universe"
217
+ },
218
+ "original": {
219
+ "dir": "common/utils/python-builder",
220
+ "rev": "2490a24f91f075f7580cd0b9df5bc01dbc467a50",
221
+ "shallow": true,
222
+ "type": "git",
223
+ "url": "ssh://git@gitlab.com/fluidattacks/universe"
224
+ }
225
+ },
273
226
  "root": {
274
227
  "inputs": {
275
- "observes_flake_builder": "observes_flake_builder"
228
+ "nixpkgs": "nixpkgs",
229
+ "python_builder": "python_builder"
276
230
  }
277
231
  },
278
232
  "shell-helpers": {
279
233
  "inputs": {
280
234
  "flake-parts": "flake-parts",
281
235
  "nixpkgs": [
282
- "observes_flake_builder",
236
+ "python_builder",
283
237
  "nixpkgs_flake"
284
238
  ]
285
239
  },
286
240
  "locked": {
287
241
  "dir": "common/utils/shell-helpers",
288
- "lastModified": 1762806066,
289
- "narHash": "sha256-Wz99Fl7SpPU1NkTHJ36XOo6DjOEAMXCw3ThRABOS2Hs=",
242
+ "lastModified": 1787145059,
243
+ "narHash": "sha256-i5i+qLR9JhcNasrQvzG4S/0AotpZAqTHXa4/68MmvwA=",
290
244
  "ref": "refs/heads/trunk",
291
- "rev": "d73cfdc7ae9e7f547e22a4481d4c2ccce38b26a8",
245
+ "rev": "e0d58302690af6f38b7544265e59c625b63df76f",
292
246
  "shallow": true,
293
247
  "type": "git",
294
248
  "url": "ssh://git@gitlab.com/fluidattacks/universe"
295
249
  },
296
250
  "original": {
297
251
  "dir": "common/utils/shell-helpers",
298
- "rev": "d73cfdc7ae9e7f547e22a4481d4c2ccce38b26a8",
252
+ "rev": "e0d58302690af6f38b7544265e59c625b63df76f",
299
253
  "shallow": true,
300
254
  "type": "git",
301
255
  "url": "ssh://git@gitlab.com/fluidattacks/universe"
@@ -304,12 +258,12 @@
304
258
  "uv2nix": {
305
259
  "inputs": {
306
260
  "nixpkgs": [
307
- "observes_flake_builder",
261
+ "python_builder",
308
262
  "pyproject-build-systems",
309
263
  "nixpkgs"
310
264
  ],
311
265
  "pyproject-nix": [
312
- "observes_flake_builder",
266
+ "python_builder",
313
267
  "pyproject-build-systems",
314
268
  "pyproject-nix"
315
269
  ]
@@ -2,8 +2,10 @@
2
2
  description = "Singer target for fluidattacks warehouse";
3
3
 
4
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";
5
+ nixpkgs.url = "github:nixos/nixpkgs/2f5a153c270b70cb0f8c11f46d96d6d3bc39f4e3";
6
+ python_builder = {
7
+ url = "git+ssh://git@gitlab.com/fluidattacks/universe?shallow=1&rev=2490a24f91f075f7580cd0b9df5bc01dbc467a50&dir=common/utils/python-builder";
8
+ inputs.nixpkgs_flake.follows = "nixpkgs";
7
9
  };
8
10
  };
9
11
 
@@ -19,11 +21,10 @@
19
21
  scripts,
20
22
  }:
21
23
  import ./build {
22
- inherit nixpkgs builders scripts;
23
24
  src = import ./build/filter.nix nixpkgs.nix-filter self;
24
25
  };
25
26
  in
26
27
  {
27
- packages = inputs.observes_flake_builder.outputs.build build_args;
28
+ packages = inputs.python_builder.outputs.build build_args;
28
29
  };
29
30
  }
@@ -11,7 +11,7 @@ from ._logger import (
11
11
  set_logger,
12
12
  )
13
13
 
14
- __version__ = "4.0.0"
14
+ __version__ = "6.0.0"
15
15
 
16
16
  Unsafe.compute(set_logger(__name__, __version__))
17
17
  LOG = logging.getLogger(__name__)
@@ -1,6 +1,5 @@
1
1
  from collections.abc import Callable
2
2
  from datetime import date
3
- from typing import TypeVar
4
3
 
5
4
  from fa_purity import (
6
5
  Bool,
@@ -41,20 +40,18 @@ from fluidattacks_gitlab_sdk.ids import (
41
40
  ProjectId,
42
41
  )
43
42
 
44
- _T = TypeVar("_T")
45
43
 
46
-
47
- def decode_maybe_single(items: NewFrozenList[_T]) -> Maybe[_T]:
44
+ def decode_maybe_single[T](items: NewFrozenList[T]) -> Maybe[T]:
48
45
  return Bool.from_primitive(len(items.items) <= 1).map(
49
- lambda _: ResultTransform.get_index(items, 0).map(Maybe.some).value_or(Maybe.empty()),
50
- lambda _: Maybe.empty(),
46
+ lambda _: ResultTransform.get_index(items, 0).map(Maybe[T].some).value_or(Maybe[T].empty()),
47
+ lambda _: Maybe[T].empty(),
51
48
  )
52
49
 
53
50
 
54
- def _decode_internal_id(
51
+ def _decode_internal_id[T](
55
52
  raw: JsonObj,
56
- iid_transform: Callable[[Natural], _T],
57
- ) -> ResultE[tuple[ProjectId, _T]]:
53
+ iid_transform: Callable[[Natural], T],
54
+ ) -> ResultE[tuple[ProjectId, T]]:
58
55
  _project = (
59
56
  JsonUnfolder.require(raw, "project_id", DecodeUtils.to_int)
60
57
  .bind(Natural.from_int)
@@ -158,13 +155,15 @@ def decode_date(raw: str) -> ResultE[date]:
158
155
 
159
156
  def assert_single(item: Coproduct[JsonObj, FrozenList[JsonObj]]) -> ResultE[JsonObj]:
160
157
  return item.map(
161
- Result.success,
162
- lambda _: Result.failure(ValueError("Expected a json not a list")),
158
+ Result[JsonObj, Exception].success,
159
+ lambda _: Result[JsonObj, Exception].failure(ValueError("Expected a json not a list")),
163
160
  )
164
161
 
165
162
 
166
163
  def assert_multiple(item: Coproduct[JsonObj, FrozenList[JsonObj]]) -> ResultE[FrozenList[JsonObj]]:
167
164
  return item.map(
168
- lambda _: Result.failure(ValueError("Expected a json list not a single json")),
169
- Result.success,
165
+ lambda _: Result[FrozenList[JsonObj], Exception].failure(
166
+ ValueError("Expected a json list not a single json"),
167
+ ),
168
+ Result[FrozenList[JsonObj], Exception].success,
170
169
  )
@@ -27,7 +27,6 @@ from fluidattacks_etl_utils.retry import (
27
27
  sleep_cmd,
28
28
  )
29
29
  from fluidattacks_etl_utils.typing import (
30
- Dict,
31
30
  TypeVar,
32
31
  )
33
32
  from gql import (
@@ -38,18 +37,23 @@ from gql.transport.requests import (
38
37
  RequestsHTTPTransport,
39
38
  )
40
39
 
41
- from . import _handlers
42
40
  from ._error import (
43
41
  ApiError,
44
42
  )
43
+ from ._handlers import (
44
+ api_error_handler,
45
+ connection_error_handler,
46
+ server_error_handler,
47
+ too_many_requests_handler,
48
+ )
45
49
 
46
50
  API_ENDPOINT = "https://gitlab.com/api/graphql"
47
51
  _T = TypeVar("_T")
48
52
 
49
53
 
50
54
  def error_handler(cmd: Cmd[_T]) -> Cmd[ResultE[_T]]:
51
- return _handlers.too_many_requests_handler(
52
- _handlers.server_error_handler(_handlers.connection_error_handler(cmd)),
55
+ return too_many_requests_handler(
56
+ server_error_handler(connection_error_handler(cmd)),
53
57
  ).map(lambda a: a.bind(lambda b: b.bind(lambda c: c)))
54
58
 
55
59
 
@@ -65,12 +69,12 @@ class GraphQlGitlabClient:
65
69
  @staticmethod
66
70
  def new(token: str) -> Cmd[GraphQlGitlabClient]:
67
71
  def _new() -> GraphQlGitlabClient:
68
- headers: Dict[str, str] = {"Authorization": f"Bearer {token}"}
72
+ headers: dict[str, str] = {"Authorization": f"Bearer {token}"}
69
73
  transport = RequestsHTTPTransport(API_ENDPOINT, headers)
70
74
  client = Client(transport=transport, fetch_schema_from_transport=False)
71
75
  return GraphQlGitlabClient(_GraphQlAsmClient(client))
72
76
 
73
- return Cmd.wrap_impure(_new)
77
+ return Cmd[GraphQlGitlabClient].wrap_impure(_new)
74
78
 
75
79
  def _get(self, query: str, values: FrozenDict[str, str]) -> Cmd[JsonObj]:
76
80
  def _action() -> JsonObj:
@@ -79,11 +83,11 @@ class GraphQlGitlabClient:
79
83
  inspect.currentframe(),
80
84
  (query, str(values)),
81
85
  JsonValueFactory.from_any(
82
- self._inner.client.execute(gql(query), dict(values)), # type: ignore[misc]
86
+ self._inner.client.execute(gql(query), dict(values)), # type: ignore[misc] # pyright: ignore[reportUnknownMemberType]
83
87
  ).bind(Unfolder.to_json),
84
88
  )
85
89
 
86
- return Cmd.wrap_impure(_action)
90
+ return Cmd[JsonObj].wrap_impure(_action)
87
91
 
88
92
  def get(self, query: str, values: FrozenDict[str, str]) -> Cmd[Result[JsonObj, ApiError]]:
89
93
  result = retry_cmd(
@@ -98,4 +102,4 @@ class GraphQlGitlabClient:
98
102
  r,
99
103
  ),
100
104
  )
101
- return _handlers.api_error_handler(result)
105
+ return api_error_handler(result)
@@ -44,7 +44,7 @@ def http_status_handler(is_handled: Callable[[int], bool], cmd: Cmd[_T]) -> Cmd[
44
44
  return factory.failure(err)
45
45
  raise
46
46
 
47
- return Cmd.new_cmd(_action)
47
+ return Cmd[ResultE[_T]].new_cmd(_action)
48
48
 
49
49
 
50
50
  def api_error_handler(cmd: Cmd[_T]) -> Cmd[Result[_T, ApiError]]:
@@ -65,7 +65,7 @@ def api_error_handler(cmd: Cmd[_T]) -> Cmd[Result[_T, ApiError]]:
65
65
  )
66
66
  return factory.failure(ApiError(errors))
67
67
 
68
- return Cmd.new_cmd(_action)
68
+ return Cmd[Result[_T, ApiError]].new_cmd(_action)
69
69
 
70
70
 
71
71
  def too_many_requests_handler(cmd: Cmd[_T]) -> Cmd[ResultE[_T]]:
@@ -80,8 +80,8 @@ def server_error_handler(cmd: Cmd[_T]) -> Cmd[ResultE[_T]]:
80
80
  def connection_error_handler(cmd: Cmd[_T]) -> Cmd[ResultE[_T]]:
81
81
  def _action(unwrapper: CmdUnwrapper) -> ResultE[_T]:
82
82
  try:
83
- return Result.success(unwrapper.act(cmd))
83
+ return Result[_T, Exception].success(unwrapper.act(cmd))
84
84
  except RequestsConnectionError as err:
85
- return Result.failure(Exception(err))
85
+ return Result[_T, Exception].failure(Exception(err))
86
86
 
87
- return Cmd.new_cmd(_action)
87
+ return Cmd[ResultE[_T]].new_cmd(_action)
@@ -1,24 +1,21 @@
1
1
  from collections.abc import Callable
2
2
  from dataclasses import dataclass
3
- from typing import TypeVar
4
3
 
5
4
  from fa_purity import Coproduct, Result, ResultE, cast_exception
6
5
 
7
6
  from fluidattacks_gitlab_sdk._http_client import HTTPError, UnhandledErrors
8
7
 
9
- _T = TypeVar("_T")
10
-
11
8
 
12
9
  @dataclass
13
10
  class NotFound(Exception):
14
11
  parent: Exception | None
15
12
 
16
13
 
17
- def handle_value_error(value: Callable[[], _T]) -> ResultE[_T]:
14
+ def handle_value_error[T](value: Callable[[], T]) -> ResultE[T]:
18
15
  try:
19
- return Result.success(value())
16
+ return Result[T, Exception].success(value())
20
17
  except ValueError as error:
21
- return Result.failure(error)
18
+ return Result[T, Exception].failure(error)
22
19
 
23
20
 
24
21
  def _handle_not_found(error: HTTPError) -> Coproduct[NotFound, Exception]:
@@ -26,15 +23,15 @@ def _handle_not_found(error: HTTPError) -> Coproduct[NotFound, Exception]:
26
23
  err_code: int = error.raw.response.status_code # type: ignore[misc]
27
24
 
28
25
  if err_code == not_found_code:
29
- return Coproduct.inl(NotFound(error.raw))
30
- return Coproduct.inr(error.raw)
26
+ return Coproduct[NotFound, Exception].inl(NotFound(error.raw))
27
+ return Coproduct[NotFound, Exception].inr(error.raw)
31
28
 
32
29
 
33
30
  def handle_not_found(error: UnhandledErrors) -> Coproduct[NotFound, Exception]:
34
31
  return error.error.map(
35
- lambda e: Coproduct.inr(cast_exception(e.raw)),
32
+ lambda e: Coproduct[NotFound, Exception].inr(cast_exception(e.raw)),
36
33
  lambda c: c.map(
37
34
  _handle_not_found,
38
- lambda e: Coproduct.inr(cast_exception(e.raw)),
35
+ lambda e: Coproduct[NotFound, Exception].inr(cast_exception(e.raw)),
39
36
  ),
40
37
  )
@@ -6,9 +6,6 @@ import logging
6
6
  from dataclasses import (
7
7
  dataclass,
8
8
  )
9
- from typing import (
10
- TypeVar,
11
- )
12
9
 
13
10
  from fa_purity import (
14
11
  Cmd,
@@ -44,6 +41,7 @@ from pure_requests.retry import (
44
41
  )
45
42
 
46
43
  from ._core import (
44
+ ChunkedEncodingError,
47
45
  Credentials,
48
46
  HandledErrors,
49
47
  HTTPError,
@@ -51,18 +49,15 @@ from ._core import (
51
49
  JSONDecodeError,
52
50
  RelativeEndpoint,
53
51
  RequestException,
52
+ RequestsConnectionError,
54
53
  UnhandledErrors,
55
54
  )
56
55
 
57
56
  LOG = logging.getLogger(__name__)
58
57
 
59
58
 
60
- _S = TypeVar("_S")
61
- _F = TypeVar("_F")
62
-
63
-
64
- def _retry_cmd(retry: int, item: Result[_S, _F]) -> Cmd[Result[_S, _F]]:
65
- log = Cmd.wrap_impure(lambda: LOG.info("retry #%2s waiting...", retry))
59
+ def _retry_cmd[S, F](retry: int, item: Result[S, F]) -> Cmd[Result[S, F]]:
60
+ log = Cmd[None].wrap_impure(lambda: LOG.info("retry #%2s waiting...", retry))
66
61
  return _retry.cmd_if_fail(item, log + _retry.sleep_cmd(retry**2))
67
62
 
68
63
 
@@ -75,8 +70,21 @@ def _http_error_handler(
75
70
  429,
76
71
  )
77
72
  if err_code in range(500, 600) or err_code in handled:
78
- return HandledError.handled(HandledErrors(Coproduct.inl(error)))
79
- return HandledError.unhandled(UnhandledErrors(Coproduct.inr(Coproduct.inl(error))))
73
+ return HandledError[HandledErrors, UnhandledErrors].handled(
74
+ HandledErrors(
75
+ Coproduct[
76
+ HTTPError,
77
+ Coproduct[ChunkedEncodingError, RequestsConnectionError],
78
+ ].inl(error),
79
+ ),
80
+ )
81
+ return HandledError[HandledErrors, UnhandledErrors].unhandled(
82
+ UnhandledErrors(
83
+ Coproduct[JSONDecodeError, Coproduct[HTTPError, RequestException]].inr(
84
+ Coproduct[HTTPError, RequestException].inl(error),
85
+ ),
86
+ ),
87
+ )
80
88
 
81
89
 
82
90
  def _handled_request_exception(
@@ -84,13 +92,37 @@ def _handled_request_exception(
84
92
  ) -> HandledError[HandledErrors, UnhandledErrors]:
85
93
  return (
86
94
  error.to_chunk_error()
87
- .map(lambda e: HandledError.handled(HandledErrors(Coproduct.inr(Coproduct.inl(e)))))
95
+ .map(
96
+ lambda e: HandledError[HandledErrors, UnhandledErrors].handled(
97
+ HandledErrors(
98
+ Coproduct[
99
+ HTTPError,
100
+ Coproduct[ChunkedEncodingError, RequestsConnectionError],
101
+ ].inr(Coproduct[ChunkedEncodingError, RequestsConnectionError].inl(e)),
102
+ ),
103
+ ),
104
+ )
88
105
  .lash(
89
106
  lambda _: error.to_connection_error().map(
90
- lambda e: HandledError.handled(HandledErrors(Coproduct.inr(Coproduct.inr(e)))),
107
+ lambda e: HandledError[HandledErrors, UnhandledErrors].handled(
108
+ HandledErrors(
109
+ Coproduct[
110
+ HTTPError,
111
+ Coproduct[ChunkedEncodingError, RequestsConnectionError],
112
+ ].inr(Coproduct[ChunkedEncodingError, RequestsConnectionError].inr(e)),
113
+ ),
114
+ ),
115
+ ),
116
+ )
117
+ .value_or(
118
+ HandledError[HandledErrors, UnhandledErrors].unhandled(
119
+ UnhandledErrors(
120
+ Coproduct[JSONDecodeError, Coproduct[HTTPError, RequestException]].inr(
121
+ Coproduct[HTTPError, RequestException].inr(error),
122
+ ),
123
+ ),
91
124
  ),
92
125
  )
93
- .value_or(HandledError.unhandled(UnhandledErrors(Coproduct.inr(Coproduct.inr(error)))))
94
126
  )
95
127
 
96
128
 
@@ -99,7 +131,7 @@ def _handled_errors(
99
131
  ) -> HandledError[HandledErrors, UnhandledErrors]:
100
132
  """Classify errors."""
101
133
  return error.map(
102
- lambda _: HandledError.unhandled(UnhandledErrors(error)),
134
+ lambda _: HandledError[HandledErrors, UnhandledErrors].unhandled(UnhandledErrors(error)),
103
135
  lambda c: c.map(
104
136
  _http_error_handler,
105
137
  _handled_request_exception,
@@ -110,7 +142,11 @@ def _handled_errors(
110
142
  def _adjust_unhandled(
111
143
  error: UnhandledErrors | MaxRetriesReached,
112
144
  ) -> Coproduct[UnhandledErrors, MaxRetriesReached]:
113
- return Coproduct.inr(error) if isinstance(error, MaxRetriesReached) else Coproduct.inl(error)
145
+ return (
146
+ Coproduct[UnhandledErrors, MaxRetriesReached].inr(error)
147
+ if isinstance(error, MaxRetriesReached)
148
+ else Coproduct[UnhandledErrors, MaxRetriesReached].inl(error)
149
+ )
114
150
 
115
151
 
116
152
  @dataclass(frozen=True)
@@ -149,7 +185,7 @@ class Client1:
149
185
  ]
150
186
  ]:
151
187
  _full = self._full_endpoint(endpoint)
152
- log = Cmd.wrap_impure(
188
+ log = Cmd[None].wrap_impure(
153
189
  lambda: LOG.debug(
154
190
  "[API] get: %s\nparams = %s",
155
191
  _full,
@@ -177,7 +213,7 @@ class Client1:
177
213
  endpoint: RelativeEndpoint,
178
214
  ) -> Cmd[Result[UnitType, Coproduct[UnhandledErrors, MaxRetriesReached]]]:
179
215
  _full = self._full_endpoint(endpoint)
180
- log = Cmd.wrap_impure(lambda: LOG.info("API call (post): %s", _full))
216
+ log = Cmd[None].wrap_impure(lambda: LOG.info("API call (post): %s", _full))
181
217
  client = HttpClientFactory.new_client(None, self._headers, False)
182
218
  handled = log + client.post(
183
219
  self._full_endpoint(endpoint),
@@ -185,7 +221,9 @@ class Client1:
185
221
  Data(FrozenDict({})),
186
222
  ).map(lambda r: r.alt(RequestException)).map(
187
223
  lambda r: bind_chain(r, lambda i: response.handle_status(i).alt(HTTPError)).alt(
188
- lambda e: _handled_errors(Coproduct.inr(e)),
224
+ lambda e: _handled_errors(
225
+ Coproduct[JSONDecodeError, Coproduct[HTTPError, RequestException]].inr(e),
226
+ ),
189
227
  ),
190
228
  )
191
229
  return _retry.retry_cmd(