sovereign 0.18.1__py3-none-any.whl → 0.19.1__py3-none-any.whl
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/__init__.py +7 -3
- sovereign/context.py +18 -13
- sovereign/server.py +19 -1
- sovereign/sources/poller.py +6 -9
- sovereign/utils/entry_point_loader.py +18 -0
- {sovereign-0.18.1.dist-info → sovereign-0.19.1.dist-info}/METADATA +1 -1
- {sovereign-0.18.1.dist-info → sovereign-0.19.1.dist-info}/RECORD +10 -9
- {sovereign-0.18.1.dist-info → sovereign-0.19.1.dist-info}/LICENSE.txt +0 -0
- {sovereign-0.18.1.dist-info → sovereign-0.19.1.dist-info}/WHEEL +0 -0
- {sovereign-0.18.1.dist-info → sovereign-0.19.1.dist-info}/entry_points.txt +0 -0
sovereign/__init__.py
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import os
|
|
2
2
|
from contextvars import ContextVar
|
|
3
3
|
from typing import Type, Any, Mapping
|
|
4
|
-
from
|
|
4
|
+
from importlib.metadata import version
|
|
5
|
+
from pkg_resources import resource_filename
|
|
5
6
|
|
|
6
7
|
from fastapi.responses import JSONResponse
|
|
7
8
|
from starlette.templating import Jinja2Templates
|
|
@@ -52,9 +53,12 @@ def get_request_id() -> str:
|
|
|
52
53
|
return _request_id_ctx_var.get()
|
|
53
54
|
|
|
54
55
|
|
|
55
|
-
|
|
56
|
+
DIST_NAME = "sovereign"
|
|
57
|
+
|
|
58
|
+
__version__ = version(DIST_NAME)
|
|
56
59
|
config_path = os.getenv("SOVEREIGN_CONFIG", "file:///etc/sovereign.yaml")
|
|
57
|
-
|
|
60
|
+
|
|
61
|
+
html_templates = Jinja2Templates(resource_filename(DIST_NAME, "templates"))
|
|
58
62
|
|
|
59
63
|
try:
|
|
60
64
|
config = SovereignConfigv2(**parse_raw_configuration(config_path))
|
sovereign/context.py
CHANGED
|
@@ -26,10 +26,10 @@ class TemplateContext:
|
|
|
26
26
|
self.configured_context = configured_context
|
|
27
27
|
self.crypto = encryption_suite
|
|
28
28
|
self.disabled_suite = disabled_suite
|
|
29
|
-
# initial load
|
|
30
|
-
self.context = self.load_context_variables()
|
|
31
29
|
self.logger = logger
|
|
32
30
|
self.stats = stats
|
|
31
|
+
# initial load
|
|
32
|
+
self.context = self.load_context_variables()
|
|
33
33
|
|
|
34
34
|
async def start_refresh_context(self) -> NoReturn:
|
|
35
35
|
if self.refresh_cron is not None:
|
|
@@ -40,21 +40,26 @@ class TemplateContext:
|
|
|
40
40
|
raise RuntimeError("Failed to start refresh_context, this should never happen")
|
|
41
41
|
|
|
42
42
|
async def refresh_context(self) -> None:
|
|
43
|
-
|
|
44
|
-
self.context = self.load_context_variables()
|
|
45
|
-
self.stats.increment("context.refresh.success")
|
|
46
|
-
# pylint: disable=broad-except
|
|
47
|
-
except Exception as e:
|
|
48
|
-
self.logger(event=e)
|
|
49
|
-
self.stats.increment("context.refresh.error")
|
|
43
|
+
self.context = self.load_context_variables()
|
|
50
44
|
|
|
51
45
|
def load_context_variables(self) -> Dict[str, Any]:
|
|
52
46
|
ret = dict()
|
|
53
47
|
for k, v in self.configured_context.items():
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
48
|
+
try:
|
|
49
|
+
if isinstance(v, Loadable):
|
|
50
|
+
ret[k] = v.load()
|
|
51
|
+
elif isinstance(v, str):
|
|
52
|
+
ret[k] = Loadable.from_legacy_fmt(v).load()
|
|
53
|
+
self.stats.increment(
|
|
54
|
+
"context.refresh.success",
|
|
55
|
+
tags=[f"context:{k}"],
|
|
56
|
+
)
|
|
57
|
+
except Exception as e: # pylint: disable=broad-exception-caught
|
|
58
|
+
self.logger(event=e)
|
|
59
|
+
self.stats.increment(
|
|
60
|
+
"context.refresh.error",
|
|
61
|
+
tags=[f"context:{k}"],
|
|
62
|
+
)
|
|
58
63
|
if "crypto" not in ret:
|
|
59
64
|
ret["crypto"] = self.crypto
|
|
60
65
|
return ret
|
sovereign/server.py
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import gunicorn.app.base
|
|
2
2
|
from fastapi import FastAPI
|
|
3
|
-
from typing import Optional, Dict, Any
|
|
3
|
+
from typing import Optional, Dict, Any, Callable
|
|
4
4
|
from sovereign import asgi_config
|
|
5
5
|
from sovereign.app import app
|
|
6
|
+
from sovereign.utils.entry_point_loader import EntryPointLoader
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
class StandaloneApplication(gunicorn.app.base.BaseApplication): # type: ignore
|
|
10
|
+
_HOOKS = ["pre_fork", "post_fork"]
|
|
11
|
+
|
|
9
12
|
def __init__(
|
|
10
13
|
self, application: FastAPI, options: Optional[Dict[str, Any]] = None
|
|
11
14
|
) -> None:
|
|
15
|
+
self.loader = EntryPointLoader(*self._HOOKS)
|
|
12
16
|
self.options = options or {}
|
|
13
17
|
self.application = application
|
|
14
18
|
super().__init__()
|
|
@@ -17,6 +21,20 @@ class StandaloneApplication(gunicorn.app.base.BaseApplication): # type: ignore
|
|
|
17
21
|
for key, value in self.options.items():
|
|
18
22
|
self.cfg.set(key.lower(), value)
|
|
19
23
|
|
|
24
|
+
for hook in self._HOOKS:
|
|
25
|
+
self._install_hooks(hook)
|
|
26
|
+
|
|
27
|
+
def _install_hooks(self, name: str) -> None:
|
|
28
|
+
hooks: list[Callable[[Any, Any], None]] = [
|
|
29
|
+
ep.load() for ep in self.loader.groups[name]
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
def master_hook(server: Any, worker: Any) -> None:
|
|
33
|
+
for hook in hooks:
|
|
34
|
+
hook(server, worker)
|
|
35
|
+
|
|
36
|
+
self.cfg.set(name, master_hook)
|
|
37
|
+
|
|
20
38
|
def load(self) -> FastAPI:
|
|
21
39
|
return self.application
|
|
22
40
|
|
sovereign/sources/poller.py
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import traceback
|
|
3
3
|
from copy import deepcopy
|
|
4
|
+
from importlib.metadata import EntryPoint
|
|
4
5
|
from datetime import timedelta, datetime
|
|
5
|
-
from pkg_resources import iter_entry_points, EntryPoint
|
|
6
6
|
from typing import Iterable, Any, Dict, List, Union, Type, Optional
|
|
7
7
|
|
|
8
8
|
from glom import glom, PathAccessError
|
|
9
9
|
|
|
10
|
+
from sovereign.utils.entry_point_loader import EntryPointLoader
|
|
10
11
|
from sovereign.sources.lib import Source
|
|
11
12
|
from sovereign.modifiers.lib import Modifier, GlobalModifier
|
|
12
13
|
from sovereign.schemas import (
|
|
@@ -50,14 +51,10 @@ class SourcePoller:
|
|
|
50
51
|
self.logger = logger
|
|
51
52
|
self.stats = stats
|
|
52
53
|
|
|
53
|
-
self.entry_points
|
|
54
|
-
for entry_point in ("sources", "modifiers", "global_modifiers"):
|
|
55
|
-
self.entry_points[entry_point] = list(
|
|
56
|
-
iter_entry_points(f"sovereign.{entry_point}")
|
|
57
|
-
)
|
|
54
|
+
self.entry_points = EntryPointLoader("sources", "modifiers", "global_modifiers")
|
|
58
55
|
|
|
59
56
|
self.source_classes: Dict[str, Type[Source]] = {
|
|
60
|
-
e.name: e.load() for e in self.entry_points["sources"]
|
|
57
|
+
e.name: e.load() for e in self.entry_points.groups["sources"]
|
|
61
58
|
}
|
|
62
59
|
self.sources = [self.setup_source(s) for s in sources]
|
|
63
60
|
if not self.sources:
|
|
@@ -89,14 +86,14 @@ class SourcePoller:
|
|
|
89
86
|
if len(self.modifiers) == len(modifiers):
|
|
90
87
|
return
|
|
91
88
|
self.modifiers = self.load_modifier_entrypoints(
|
|
92
|
-
self.entry_points["modifiers"], modifiers
|
|
89
|
+
self.entry_points.groups["modifiers"], modifiers
|
|
93
90
|
)
|
|
94
91
|
|
|
95
92
|
def lazy_load_global_modifiers(self, global_modifiers: List[str]) -> None:
|
|
96
93
|
if len(self.global_modifiers) == len(global_modifiers):
|
|
97
94
|
return
|
|
98
95
|
self.global_modifiers = self.load_global_modifier_entrypoints(
|
|
99
|
-
self.entry_points["global_modifiers"], global_modifiers
|
|
96
|
+
self.entry_points.groups["global_modifiers"], global_modifiers
|
|
100
97
|
)
|
|
101
98
|
|
|
102
99
|
def load_modifier_entrypoints(
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from typing import Dict
|
|
2
|
+
from functools import cached_property
|
|
3
|
+
from importlib.metadata import entry_points, EntryPoints
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class EntryPointLoader:
|
|
7
|
+
ENTRY_POINTS = entry_points()
|
|
8
|
+
|
|
9
|
+
def __init__(self, *args: str) -> None:
|
|
10
|
+
self._groups = args
|
|
11
|
+
|
|
12
|
+
@classmethod
|
|
13
|
+
def _select(cls, group: str) -> EntryPoints:
|
|
14
|
+
return cls.ENTRY_POINTS.select(group=f"sovereign.{group}")
|
|
15
|
+
|
|
16
|
+
@cached_property
|
|
17
|
+
def groups(self) -> Dict[str, EntryPoints]:
|
|
18
|
+
return {group: self._select(group) for group in self._groups}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
sovereign/__init__.py,sha256=
|
|
1
|
+
sovereign/__init__.py,sha256=OqRozdp92NTV_6pbYNtyXsTAHxkpHTpxslhNgcrXuNY,3136
|
|
2
2
|
sovereign/app.py,sha256=z5dT5wdVNeAQap5ORRmnLpJstb1euWoj4vXZPrMttNs,4017
|
|
3
3
|
sovereign/config_loader.py,sha256=siuXN6T62Lx3JzMchnEBZ7ZDuSCFH73oWuUk-oTOVQQ,6382
|
|
4
|
-
sovereign/context.py,sha256=
|
|
4
|
+
sovereign/context.py,sha256=VswYtHZNcRMMT-Dlx9CBTxLo398uRXUPl6N--VcqybE,4411
|
|
5
5
|
sovereign/discovery.py,sha256=EIghvk_HMYp14WzEG1aQhnsoGcLXMWSrCncPobJST4c,5885
|
|
6
6
|
sovereign/error_info.py,sha256=r2KXBYq9Fo7AI2pmIpATWFm0pykr2MqfrKH0WWW5Sfk,1488
|
|
7
7
|
sovereign/logs.py,sha256=DZK6F3LMxhch96qFasdXA6NPlQHJcKbjD83_S8W6Rds,4340
|
|
@@ -10,12 +10,12 @@ sovereign/modifiers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSu
|
|
|
10
10
|
sovereign/modifiers/lib.py,sha256=DbXsxrrjnFE4Y7rbwpeiM5tS5w5NBwSdYH58AtDTP0I,2884
|
|
11
11
|
sovereign/modifiers/test.py,sha256=7_c2hWXn_sYJ6997N1_uSWtClOikcOzu1yRCY56-l-4,361
|
|
12
12
|
sovereign/schemas.py,sha256=jCW9WSjZ7SP8ycloYtC-6KG0Vj0VRBOesSTKa0kymrQ,27367
|
|
13
|
-
sovereign/server.py,sha256=
|
|
13
|
+
sovereign/server.py,sha256=z8Uz1UYIZix0S40Srk774WIMDN2jl2SozO8irib0wc4,1402
|
|
14
14
|
sovereign/sources/__init__.py,sha256=g9hEpFk8j5i1ApHQpbc9giTyJW41Ppgsqv5P9zGxOJk,78
|
|
15
15
|
sovereign/sources/file.py,sha256=A4UWoRU39v2Ex5Mtdl_uw53iMkslYylF4CiiwW7LOpk,689
|
|
16
16
|
sovereign/sources/inline.py,sha256=bNqVZyelcUofYBWHFOUIhOUU9az32CdBEfaYRzNzFFE,1002
|
|
17
17
|
sovereign/sources/lib.py,sha256=LIbnlKkL0bQT10y4GT2E8yypjYxqfJYbB9FkGB5C2oc,1030
|
|
18
|
-
sovereign/sources/poller.py,sha256=
|
|
18
|
+
sovereign/sources/poller.py,sha256=byxlEfhB1m2Uhzpi3wlknNLKRRQ47o56VuYLZrrFq1Q,10940
|
|
19
19
|
sovereign/static/sass/style.scss,sha256=tPHPEm3sZeBFGDyyn3pHcA-nbaKT-h-UsSTsf6dHNDU,1158
|
|
20
20
|
sovereign/static/style.css,sha256=vG8HPsbCbPIZfHgy7gSeof97Pnp0okkyaXyJzIEEW-8,447517
|
|
21
21
|
sovereign/statistics.py,sha256=Xfj4oWMfCkbYc2ibF7rDUpbw6Zw6dI4N5BpCLDQc4j4,2336
|
|
@@ -28,6 +28,7 @@ sovereign/utils/auth.py,sha256=9rruWP-Ok8ec9l_MzWY3oUZKI8s7jt0Dmx3kHWnTRgQ,1772
|
|
|
28
28
|
sovereign/utils/crypto.py,sha256=jNM3YRgdkxmTEeEDftkXnn33rr2qmT1-_3n3DUUdzRE,3438
|
|
29
29
|
sovereign/utils/dictupdate.py,sha256=JkDjg16u7sW6A_4Q2oX1PY_MtJU7m1VivZWn9VLZ9V8,2559
|
|
30
30
|
sovereign/utils/eds.py,sha256=3NwvQpFMxeWJ8pT1XhzqikrgT26HjObms4Ieh3hivOM,3894
|
|
31
|
+
sovereign/utils/entry_point_loader.py,sha256=BEVodk-um70RvT1nSOu_IB-hr1K4ppthXod0VZEiZJ8,526
|
|
31
32
|
sovereign/utils/mock.py,sha256=UCWiZ7PsRxvDL9OmSXUuzuGPri2s69IABXLALZHWGII,1269
|
|
32
33
|
sovereign/utils/templates.py,sha256=FE_H_oE7VrS3X_VN1z_g10b9-rpmi1_gL-cMxi5XtXU,1057
|
|
33
34
|
sovereign/utils/timer.py,sha256=_dUtEasj0BKbWYuQ_T3HFIyjurXXj-La-dNSMAwKMSo,795
|
|
@@ -39,8 +40,8 @@ sovereign/views/crypto.py,sha256=nxp6bkPU9GZw_zOk0fsJdz_XRQPXxPI6cXQDL9-cigU,204
|
|
|
39
40
|
sovereign/views/discovery.py,sha256=dPX0auMsQCCura7eIq-jEGQoS92Avs9QPAsPGDjWL5I,5902
|
|
40
41
|
sovereign/views/healthchecks.py,sha256=_WkMunlrFpqGTLgtNtRr7gCsDCv5kiuYxCyTi-dMEKM,1357
|
|
41
42
|
sovereign/views/interface.py,sha256=2wXb5Kf5CbY_X37dr1v-3Uoep04abvv8x7BaUTNqsPg,7093
|
|
42
|
-
sovereign-0.
|
|
43
|
-
sovereign-0.
|
|
44
|
-
sovereign-0.
|
|
45
|
-
sovereign-0.
|
|
46
|
-
sovereign-0.
|
|
43
|
+
sovereign-0.19.1.dist-info/entry_points.txt,sha256=kOn848ucVbNvtsGABDuwzOHmNiOb0Ey8dV85Z3dLv3Y,222
|
|
44
|
+
sovereign-0.19.1.dist-info/LICENSE.txt,sha256=2X125zvAb9AYLjCgdMDQZuufhm0kwcg31A8pGKj_-VY,560
|
|
45
|
+
sovereign-0.19.1.dist-info/WHEEL,sha256=vxFmldFsRN_Hx10GDvsdv1wroKq8r5Lzvjp6GZ4OO8c,88
|
|
46
|
+
sovereign-0.19.1.dist-info/METADATA,sha256=gUIo4dFBvurdReBiftpAOL1Je9CbcitbtcigturyikU,6417
|
|
47
|
+
sovereign-0.19.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|