sovereign 1.0.0b102__tar.gz → 1.0.0b104__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.
Potentially problematic release.
This version of sovereign might be problematic. Click here for more details.
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/PKG-INFO +1 -1
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/pyproject.toml +1 -1
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/schemas.py +3 -1
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/sources/poller.py +145 -45
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/statistics.py +6 -4
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/views/api.py +2 -3
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/LICENSE.txt +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/README.md +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/__init__.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/app.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/cache.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/constants.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/context.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/dynamic_config/__init__.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/dynamic_config/deser.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/dynamic_config/loaders.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/error_info.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/logging/access_logger.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/logging/application_logger.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/logging/base_logger.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/logging/bootstrapper.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/logging/types.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/middlewares.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/modifiers/__init__.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/modifiers/lib.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/rendering.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/response_class.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/server.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/sources/__init__.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/sources/file.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/sources/inline.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/sources/lib.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/static/node_expression.js +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/static/panel.js +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/static/sass/style.scss +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/static/style.css +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/templates/base.html +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/templates/err.html +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/templates/resources.html +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/testing/loaders.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/testing/modifiers.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/tracing.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/utils/__init__.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/utils/auth.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/utils/crypto/__init__.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/utils/crypto/crypto.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/utils/crypto/suites/__init__.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/utils/crypto/suites/aes_gcm_cipher.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/utils/crypto/suites/base_cipher.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/utils/crypto/suites/disabled_cipher.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/utils/crypto/suites/fernet_cipher.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/utils/dictupdate.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/utils/eds.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/utils/entry_point_loader.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/utils/mock.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/utils/resources.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/utils/templates.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/utils/timer.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/utils/version_info.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/utils/weighted_clusters.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/views/__init__.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/views/crypto.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/views/discovery.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/views/healthchecks.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/views/interface.py +0 -0
- {sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/worker.py +0 -0
|
@@ -44,7 +44,7 @@ class CacheStrategy(str, Enum):
|
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
class SourceData(BaseModel):
|
|
47
|
-
scopes: Dict[str, List[Dict[str, Any]]] =
|
|
47
|
+
scopes: Dict[str, List[Dict[str, Any]]] = Field(default_factory=dict)
|
|
48
48
|
|
|
49
49
|
|
|
50
50
|
class ConfiguredSource(BaseModel):
|
|
@@ -716,6 +716,8 @@ class ContextConfiguration(BaseSettings):
|
|
|
716
716
|
|
|
717
717
|
class SourcesConfiguration(BaseSettings):
|
|
718
718
|
refresh_rate: int = Field(30, alias="SOVEREIGN_SOURCES_REFRESH_RATE")
|
|
719
|
+
max_retries: int = Field(3, alias="SOVEREIGN_SOURCES_MAX_RETRIES")
|
|
720
|
+
retry_delay: int = Field(1, alias="SOVEREIGN_SOURCES_RETRY_DELAY")
|
|
719
721
|
cache_strategy: Optional[Any] = None
|
|
720
722
|
model_config = SettingsConfigDict(
|
|
721
723
|
env_file=".env",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import uuid
|
|
2
3
|
import asyncio
|
|
3
4
|
import traceback
|
|
4
5
|
from copy import deepcopy
|
|
@@ -33,29 +34,74 @@ Mods = Dict[str, Type[Modifier]]
|
|
|
33
34
|
GMods = Dict[str, Type[GlobalModifier]]
|
|
34
35
|
|
|
35
36
|
|
|
36
|
-
def
|
|
37
|
-
if not isinstance(old, dict) or not isinstance(new, dict):
|
|
38
|
-
return ["content_changed"]
|
|
39
|
-
|
|
37
|
+
def _deep_diff(old, new, path="") -> list[dict[str, Any]]:
|
|
40
38
|
changes = []
|
|
41
|
-
all_keys = set(old.keys()) | set(new.keys())
|
|
42
39
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
# handle add/remove
|
|
41
|
+
if (old, new) == (None, None):
|
|
42
|
+
return changes
|
|
43
|
+
elif old is None:
|
|
44
|
+
changes.append({"op": "add", "path": path, "value": new})
|
|
45
|
+
return changes
|
|
46
|
+
elif new is None:
|
|
47
|
+
changes.append({"op": "remove", "path": path, "old_value": old})
|
|
48
|
+
return changes
|
|
49
|
+
|
|
50
|
+
# handle completely different types
|
|
51
|
+
if type(old) is not type(new):
|
|
52
|
+
changes.append(
|
|
53
|
+
{"op": "change", "path": path, "old_value": old, "new_value": new}
|
|
54
|
+
)
|
|
55
|
+
return changes
|
|
56
|
+
|
|
57
|
+
# handle fields recursively
|
|
58
|
+
if isinstance(old, dict) and isinstance(new, dict):
|
|
59
|
+
all_keys = set(old.keys()) | set(new.keys())
|
|
60
|
+
|
|
61
|
+
for key in sorted(all_keys):
|
|
62
|
+
old_val = old.get(key)
|
|
63
|
+
new_val = new.get(key)
|
|
64
|
+
|
|
65
|
+
current_path = f"{path}.{key}" if path else key
|
|
46
66
|
|
|
47
|
-
if old_val != new_val:
|
|
48
67
|
if key not in old:
|
|
49
|
-
changes.append(
|
|
68
|
+
changes.append({"op": "add", "path": current_path, "value": new_val})
|
|
50
69
|
elif key not in new:
|
|
51
|
-
changes.append(
|
|
52
|
-
|
|
53
|
-
|
|
70
|
+
changes.append(
|
|
71
|
+
{"op": "remove", "path": current_path, "old_value": old_val}
|
|
72
|
+
)
|
|
73
|
+
elif old_val != new_val:
|
|
74
|
+
nested_changes = _deep_diff(old_val, new_val, current_path)
|
|
75
|
+
changes.extend(nested_changes)
|
|
76
|
+
|
|
77
|
+
# handle items recursively
|
|
78
|
+
elif isinstance(old, list) and isinstance(new, list):
|
|
79
|
+
max_len = max(len(old), len(new))
|
|
80
|
+
|
|
81
|
+
for i in range(max_len):
|
|
82
|
+
current_path = f"{path}[{i}]" if path else f"[{i}]"
|
|
83
|
+
|
|
84
|
+
if i >= len(old):
|
|
85
|
+
changes.append({"op": "add", "path": current_path, "value": new[i]})
|
|
86
|
+
elif i >= len(new):
|
|
87
|
+
changes.append(
|
|
88
|
+
{"op": "remove", "path": current_path, "old_value": old[i]}
|
|
89
|
+
)
|
|
90
|
+
elif old[i] != new[i]:
|
|
91
|
+
nested_changes = _deep_diff(old[i], new[i], current_path)
|
|
92
|
+
changes.extend(nested_changes)
|
|
93
|
+
|
|
94
|
+
# handle primitives
|
|
95
|
+
else:
|
|
96
|
+
if old != new:
|
|
97
|
+
changes.append(
|
|
98
|
+
{"op": "change", "path": path, "old_value": old, "new_value": new}
|
|
99
|
+
)
|
|
54
100
|
|
|
55
101
|
return changes
|
|
56
102
|
|
|
57
103
|
|
|
58
|
-
def per_field_diff(old, new):
|
|
104
|
+
def per_field_diff(old, new) -> list[dict[str, Any]]:
|
|
59
105
|
changes = []
|
|
60
106
|
max_len = max(len(old), len(new))
|
|
61
107
|
|
|
@@ -64,45 +110,64 @@ def per_field_diff(old, new):
|
|
|
64
110
|
new_inst = new[i] if i < len(new) else None
|
|
65
111
|
|
|
66
112
|
if old_inst is None:
|
|
67
|
-
changes.append(f"
|
|
113
|
+
changes.append({"op": "add", "path": f"[{i}]", "value": new_inst})
|
|
68
114
|
elif new_inst is None:
|
|
69
|
-
changes.append(f"
|
|
115
|
+
changes.append({"op": "remove", "path": f"[{i}]", "old_value": old_inst})
|
|
70
116
|
elif old_inst != new_inst:
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
117
|
+
# Use the deep diff with index prefix
|
|
118
|
+
field_changes = _deep_diff(old_inst, new_inst, f"[{i}]")
|
|
119
|
+
changes.extend(field_changes)
|
|
74
120
|
|
|
75
121
|
return changes
|
|
76
122
|
|
|
77
123
|
|
|
78
|
-
def
|
|
124
|
+
def _gen_uuid(diff_summary: dict[str, Any]) -> str:
|
|
125
|
+
blob = json.dumps(diff_summary, sort_keys=True, separators=("", ""))
|
|
126
|
+
return str(uuid.uuid5(uuid.NAMESPACE_DNS, blob))
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def source_diff_summary(prev, curr) -> dict[str, Any]:
|
|
79
130
|
if prev is None:
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
131
|
+
summary = {
|
|
132
|
+
"type": "initial_load",
|
|
133
|
+
"scopes": {
|
|
134
|
+
scope: {"added": len(instances)}
|
|
135
|
+
for scope, instances in curr.scopes.items()
|
|
136
|
+
if instances
|
|
137
|
+
},
|
|
138
|
+
}
|
|
139
|
+
else:
|
|
140
|
+
summary = {"type": "update", "scopes": {}}
|
|
141
|
+
|
|
142
|
+
all_scopes = set(prev.scopes.keys()) | set(curr.scopes.keys())
|
|
143
|
+
|
|
144
|
+
for scope in sorted(all_scopes):
|
|
145
|
+
old = prev.scopes.get(scope, [])
|
|
146
|
+
new = curr.scopes.get(scope, [])
|
|
85
147
|
|
|
86
|
-
|
|
87
|
-
|
|
148
|
+
n_old = len(old)
|
|
149
|
+
n_new = len(new)
|
|
88
150
|
|
|
89
|
-
|
|
90
|
-
old = prev.scopes.get(scope, [])
|
|
91
|
-
new = curr.scopes.get(scope, [])
|
|
151
|
+
scope_changes = {}
|
|
92
152
|
|
|
93
|
-
|
|
94
|
-
|
|
153
|
+
if n_old == 0 and n_new > 0:
|
|
154
|
+
scope_changes["added"] = n_new
|
|
155
|
+
elif n_old > 0 and n_new == 0:
|
|
156
|
+
scope_changes["removed"] = n_old
|
|
157
|
+
elif old != new:
|
|
158
|
+
detailed_changes = per_field_diff(old, new)
|
|
159
|
+
if detailed_changes:
|
|
160
|
+
scope_changes["field_changes"] = detailed_changes
|
|
161
|
+
scope_changes["count_change"] = n_new - n_old
|
|
95
162
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
elif n_old > 0 and n_new == 0:
|
|
99
|
-
summary.append(f"scope:{scope} removed:{n_old} instances")
|
|
100
|
-
elif old != new:
|
|
101
|
-
detailed_changes = per_field_diff(old, new)
|
|
102
|
-
if detailed_changes:
|
|
103
|
-
summary.append(f"scope:{scope} changes: {'; '.join(detailed_changes)}")
|
|
163
|
+
if scope_changes:
|
|
164
|
+
summary["scopes"][scope] = scope_changes
|
|
104
165
|
|
|
105
|
-
|
|
166
|
+
if not summary["scopes"]:
|
|
167
|
+
summary = {"type": "no_changes"}
|
|
168
|
+
|
|
169
|
+
summary["uuid"] = _gen_uuid(summary)
|
|
170
|
+
return summary
|
|
106
171
|
|
|
107
172
|
|
|
108
173
|
class SourcePoller:
|
|
@@ -137,13 +202,17 @@ class SourcePoller:
|
|
|
137
202
|
self.global_modifiers: GMods = dict()
|
|
138
203
|
|
|
139
204
|
# initially set data and modify
|
|
140
|
-
self.source_data: SourceData
|
|
205
|
+
self.source_data: SourceData = SourceData()
|
|
206
|
+
self.source_data_modified: SourceData = SourceData()
|
|
141
207
|
self.last_updated = datetime.now()
|
|
142
208
|
self.instance_count = 0
|
|
143
209
|
|
|
144
210
|
self.cache: dict[str, dict[str, list[dict[str, Any]]]] = {}
|
|
145
211
|
self.registry: set[Any] = set()
|
|
146
212
|
|
|
213
|
+
# Retry state
|
|
214
|
+
self.retry_count = 0
|
|
215
|
+
|
|
147
216
|
@property
|
|
148
217
|
def data_is_stale(self) -> bool:
|
|
149
218
|
return self.last_updated < datetime.now() - timedelta(minutes=2)
|
|
@@ -226,20 +295,37 @@ class SourcePoller:
|
|
|
226
295
|
|
|
227
296
|
def refresh(self) -> bool:
|
|
228
297
|
self.stats.increment("sources.attempt")
|
|
298
|
+
|
|
299
|
+
# Get retry config from global source config
|
|
300
|
+
max_retries = config.source_config.max_retries
|
|
301
|
+
|
|
229
302
|
try:
|
|
230
303
|
new = SourceData()
|
|
231
304
|
for source in self.sources:
|
|
232
|
-
|
|
305
|
+
scope = source.scope
|
|
306
|
+
if scope not in new.scopes:
|
|
307
|
+
new.scopes[scope] = []
|
|
308
|
+
new.scopes[scope].extend(source.get())
|
|
233
309
|
except Exception as e:
|
|
310
|
+
self.retry_count += 1
|
|
234
311
|
self.logger.error(
|
|
235
|
-
event="Error while refreshing sources",
|
|
312
|
+
event=f"Error while refreshing sources (attempt {self.retry_count}/{max_retries})",
|
|
236
313
|
traceback=[line for line in traceback.format_exc().split("\n")],
|
|
237
314
|
error=e.__class__.__name__,
|
|
238
315
|
detail=getattr(e, "detail", "-"),
|
|
316
|
+
retry_count=self.retry_count,
|
|
239
317
|
)
|
|
240
318
|
self.stats.increment("sources.error")
|
|
319
|
+
|
|
320
|
+
if self.retry_count >= max_retries:
|
|
321
|
+
# Reset retry count for next cycle
|
|
322
|
+
self.retry_count = 0
|
|
323
|
+
self.stats.increment("sources.error.final")
|
|
241
324
|
return False
|
|
242
325
|
|
|
326
|
+
# Success - reset retry count
|
|
327
|
+
self.retry_count = 0
|
|
328
|
+
|
|
243
329
|
# Is the new data the same as what we currently have
|
|
244
330
|
if new == getattr(self, "source_data", None):
|
|
245
331
|
self.stats.increment("sources.unchanged")
|
|
@@ -345,6 +431,8 @@ class SourcePoller:
|
|
|
345
431
|
or is_debug_request(node_value)
|
|
346
432
|
)
|
|
347
433
|
if match:
|
|
434
|
+
if scope not in ret.scopes:
|
|
435
|
+
ret.scopes[scope] = []
|
|
348
436
|
ret.scopes[scope].append(instance)
|
|
349
437
|
return ret
|
|
350
438
|
|
|
@@ -406,5 +494,17 @@ class SourcePoller:
|
|
|
406
494
|
while True:
|
|
407
495
|
try:
|
|
408
496
|
self.poll()
|
|
409
|
-
|
|
497
|
+
|
|
498
|
+
# If we have retry count, use exponential backoff for next attempt
|
|
499
|
+
if self.retry_count > 0:
|
|
500
|
+
retry_delay = config.source_config.retry_delay
|
|
501
|
+
delay = min(
|
|
502
|
+
retry_delay * (2 ** (self.retry_count - 1)),
|
|
503
|
+
self.source_refresh_rate, # Cap at normal refresh rate
|
|
504
|
+
)
|
|
505
|
+
await asyncio.sleep(delay)
|
|
506
|
+
else:
|
|
507
|
+
await asyncio.sleep(self.source_refresh_rate)
|
|
508
|
+
except Exception as e:
|
|
509
|
+
self.logger.error(f"Unexpected error in poll loop: {e}")
|
|
410
510
|
await asyncio.sleep(self.source_refresh_rate)
|
|
@@ -53,10 +53,12 @@ def configure_statsd() -> StatsDProxy:
|
|
|
53
53
|
from datadog import DogStatsd
|
|
54
54
|
|
|
55
55
|
class CustomStatsd(DogStatsd): # type: ignore
|
|
56
|
-
def _report(self,
|
|
57
|
-
super()._report(
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
def _report(self, *args, **kwargs) -> None: # type: ignore
|
|
57
|
+
super()._report(*args, **kwargs)
|
|
58
|
+
# Capture the metric name and increment its count for debugging
|
|
59
|
+
if metric := kwargs.get("metric"):
|
|
60
|
+
self.emitted: Dict[str, Any] = dict()
|
|
61
|
+
self.emitted[metric] = self.emitted.setdefault(metric, 0) + 1
|
|
60
62
|
|
|
61
63
|
module: Optional[CustomStatsd]
|
|
62
64
|
module = CustomStatsd()
|
|
@@ -37,8 +37,8 @@ async def resource(
|
|
|
37
37
|
) -> Response:
|
|
38
38
|
expressions = [f"cluster={service_cluster}"]
|
|
39
39
|
try:
|
|
40
|
-
|
|
41
|
-
for expr in expand_metadata_to_expr(
|
|
40
|
+
data = {"metadata": json.loads(metadata or "{}")}
|
|
41
|
+
for expr in expand_metadata_to_expr(data):
|
|
42
42
|
expressions.append(expr)
|
|
43
43
|
except Exception:
|
|
44
44
|
pass
|
|
@@ -51,7 +51,6 @@ async def resource(
|
|
|
51
51
|
expressions=expressions,
|
|
52
52
|
)
|
|
53
53
|
req = mock_discovery_request(**{k: v for k, v in kwargs.items() if v is not None})
|
|
54
|
-
print(req)
|
|
55
54
|
response = await cache.blocking_read(req)
|
|
56
55
|
if content := getattr(response, "text", None):
|
|
57
56
|
return Response(content, media_type="application/json")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/utils/crypto/suites/aes_gcm_cipher.py
RENAMED
|
File without changes
|
{sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/utils/crypto/suites/base_cipher.py
RENAMED
|
File without changes
|
{sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/utils/crypto/suites/disabled_cipher.py
RENAMED
|
File without changes
|
{sovereign-1.0.0b102 → sovereign-1.0.0b104}/src/sovereign/utils/crypto/suites/fernet_cipher.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|