fred-oss 0.55.0__tar.gz → 0.56.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.
- {fred_oss-0.55.0/src/main/fred_oss.egg-info → fred_oss-0.56.0}/PKG-INFO +1 -1
- fred_oss-0.56.0/src/main/fred/cli/main.py +59 -0
- fred_oss-0.56.0/src/main/fred/rest/__init__.py +17 -0
- fred_oss-0.56.0/src/main/fred/rest/auth.py +23 -0
- fred_oss-0.56.0/src/main/fred/rest/config.py +32 -0
- fred_oss-0.56.0/src/main/fred/rest/router/catalog/default/__init__.py +10 -0
- fred_oss-0.56.0/src/main/fred/rest/router/catalog/default/_base.py +29 -0
- fred_oss-0.56.0/src/main/fred/rest/router/catalog/default/_example.py +31 -0
- fred_oss-0.56.0/src/main/fred/rest/router/catalog/default/catalog.py +20 -0
- fred_oss-0.56.0/src/main/fred/rest/router/catalog/interface.py +11 -0
- fred_oss-0.56.0/src/main/fred/rest/router/config.py +40 -0
- fred_oss-0.56.0/src/main/fred/rest/router/endpoint.py +94 -0
- fred_oss-0.56.0/src/main/fred/rest/router/interface.py +90 -0
- fred_oss-0.56.0/src/main/fred/rest/server.py +104 -0
- fred_oss-0.56.0/src/main/fred/rest/settings.py +46 -0
- fred_oss-0.56.0/src/main/fred/version +1 -0
- fred_oss-0.56.0/src/main/fred/worker/runner/rest/__init__.py +0 -0
- fred_oss-0.56.0/src/main/fred/worker/runner/rest/routers/__init__.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0/src/main/fred_oss.egg-info}/PKG-INFO +1 -1
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred_oss.egg-info/SOURCES.txt +15 -0
- fred_oss-0.55.0/src/main/fred/cli/main.py +0 -31
- fred_oss-0.55.0/src/main/fred/version +0 -1
- {fred_oss-0.55.0 → fred_oss-0.56.0}/MANIFEST.in +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/NOTICE.txt +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/README.md +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/requirements.txt +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/setup.cfg +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/setup.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/cli/__init__.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/cli/__main__.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/cli/interface.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/dao/__init__.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/dao/comp/__init__.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/dao/comp/_keyval.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/dao/comp/_pubsub.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/dao/comp/_queue.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/dao/comp/catalog.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/dao/comp/interface.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/dao/service/__init__.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/dao/service/_minio/__init__.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/dao/service/_minio/policy/__init__.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/dao/service/_minio/policy/builder.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/dao/service/_minio/policy/catalog.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/dao/service/_minio/policy/loader.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/dao/service/_minio/policy/templates/public_ro.json +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/dao/service/_minio/policy/templates/public_rw.json +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/dao/service/_minio/pool.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/dao/service/_minio/service.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/dao/service/_redis.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/dao/service/_stdlib.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/dao/service/catalog.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/dao/service/interface.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/dao/service/utils.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/future/__init__.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/future/callback/__init__.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/future/callback/_function.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/future/callback/catalog.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/future/callback/interface.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/future/impl.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/future/result.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/future/settings.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/future/utils.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/integrations/databricks/__init__.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/integrations/databricks/cli_ext.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/integrations/databricks/runtime.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/integrations/databricks/runtimes/16.4LTS.json +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/integrations/databricks/runtimes/__init__.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/integrations/databricks/runtimes/scanner.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/integrations/databricks/runtimes/sync.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/integrations/databricks/wrappers/__init__.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/integrations/databricks/wrappers/dbutils.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/integrations/runpod/__init__.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/integrations/runpod/cli_ext.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/integrations/runpod/helper.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/maturity.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/monad/__init__.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/monad/_either.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/monad/catalog.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/monad/interface.py +0 -0
- {fred_oss-0.55.0/src/main/fred/utils → fred_oss-0.56.0/src/main/fred/rest/router}/__init__.py +0 -0
- {fred_oss-0.55.0/src/main/fred/utils/imout → fred_oss-0.56.0/src/main/fred/rest/router/catalog}/__init__.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/settings.py +0 -0
- {fred_oss-0.55.0/src/main/fred/worker/runner/model → fred_oss-0.56.0/src/main/fred/utils}/__init__.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/utils/dateops.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/utils/imops.py +0 -0
- {fred_oss-0.55.0/src/main/fred/worker/runner/plugins → fred_oss-0.56.0/src/main/fred/utils/imout}/__init__.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/utils/imout/_filesystem.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/utils/imout/_minio.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/utils/imout/_string.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/utils/imout/catalog.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/utils/imout/interface.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/utils/mlops/__init__.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/utils/mlops/auto.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/utils/runtime.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/version.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/worker/__init__.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/worker/interface.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/worker/runner/__init__.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/worker/runner/backend.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/worker/runner/client.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/worker/runner/handler.py +0 -0
- {fred_oss-0.55.0/src/main/fred/worker/runner/rest → fred_oss-0.56.0/src/main/fred/worker/runner/model}/__init__.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/worker/runner/model/_handler.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/worker/runner/model/_item.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/worker/runner/model/_request.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/worker/runner/model/_runner_spec.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/worker/runner/model/catalog.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/worker/runner/model/interface.py +0 -0
- {fred_oss-0.55.0/src/main/fred/worker/runner/rest/routers → fred_oss-0.56.0/src/main/fred/worker/runner/plugins}/__init__.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/worker/runner/plugins/_local.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/worker/runner/plugins/_runpod.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/worker/runner/plugins/catalog.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/worker/runner/plugins/interface.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/worker/runner/rest/auth.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/worker/runner/rest/cli_ext.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/worker/runner/rest/routers/_runner.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/worker/runner/rest/routers/catalog.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/worker/runner/rest/routers/interface.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/worker/runner/rest/server.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/worker/runner/rest/settings.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/worker/runner/settings.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/worker/runner/signal.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/worker/runner/status.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/worker/runner/utils.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/worker/settings.py +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred_oss.egg-info/dependency_links.txt +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred_oss.egg-info/entry_points.txt +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred_oss.egg-info/requires.txt +0 -0
- {fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred_oss.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from fred.version import version
|
|
4
|
+
from fred.settings import logger_manager
|
|
5
|
+
from fred.cli.interface import AbstractCLI
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
logger = logger_manager.get_logger(name=__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class CLIExtensionGroups:
|
|
12
|
+
"""CLI Extensions providing access to various integrations by following a lazy loading pattern."""
|
|
13
|
+
|
|
14
|
+
@property
|
|
15
|
+
def databricks(self):
|
|
16
|
+
from fred.integrations.databricks.cli_ext import DatabricksExt
|
|
17
|
+
return DatabricksExt()
|
|
18
|
+
|
|
19
|
+
@property
|
|
20
|
+
def runpod(self):
|
|
21
|
+
from fred.integrations.runpod.cli_ext import RunPodExt
|
|
22
|
+
return RunPodExt()
|
|
23
|
+
|
|
24
|
+
@property
|
|
25
|
+
def runner_server(self):
|
|
26
|
+
from fred.worker.runner.rest.cli_ext import RunnerServerExt
|
|
27
|
+
return RunnerServerExt()
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class CLI(AbstractCLI, CLIExtensionGroups):
|
|
31
|
+
|
|
32
|
+
def version(self) -> str:
|
|
33
|
+
return version.value
|
|
34
|
+
|
|
35
|
+
def serve(
|
|
36
|
+
self,
|
|
37
|
+
classname: Optional[str] = None,
|
|
38
|
+
classpath: Optional[str] = None,
|
|
39
|
+
include_routers: Optional[list[str]] = None,
|
|
40
|
+
exclude_routers: Optional[list[str]] = None,
|
|
41
|
+
fastapi_configs: Optional[dict] = None,
|
|
42
|
+
server_configs: Optional[dict] = None,
|
|
43
|
+
):
|
|
44
|
+
from fred.rest.server import FredServer
|
|
45
|
+
|
|
46
|
+
include_routers = include_routers or []
|
|
47
|
+
exclude_routers = exclude_routers or []
|
|
48
|
+
fastapi_configs = fastapi_configs or {}
|
|
49
|
+
server_configs = server_configs or {}
|
|
50
|
+
|
|
51
|
+
logger.info("Starting the Fred-REST Server...")
|
|
52
|
+
server = FredServer.auto(
|
|
53
|
+
include_routers=include_routers,
|
|
54
|
+
exclude_routers=exclude_routers,
|
|
55
|
+
router_classname=classname,
|
|
56
|
+
router_classpath=classpath,
|
|
57
|
+
**fastapi_configs,
|
|
58
|
+
)
|
|
59
|
+
server.start(**server_configs)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""
|
|
2
|
+
[Fred-REST] Fred's Simple Extensible REST-API Server
|
|
3
|
+
========================================================
|
|
4
|
+
This module provides a simple and extensible REST-API server implementation using FastAPI.
|
|
5
|
+
It includes configurations for authentication, router management, and server startup.
|
|
6
|
+
"""
|
|
7
|
+
from fred.maturity import Maturity, MaturityLevel
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
module_maturity = Maturity(
|
|
11
|
+
level=MaturityLevel.ALPHA,
|
|
12
|
+
reference=__name__,
|
|
13
|
+
message=(
|
|
14
|
+
"Fred-REST implementation is in early development "
|
|
15
|
+
"and therefore currently with incomplete and unstable features."
|
|
16
|
+
)
|
|
17
|
+
)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from fastapi import Security, HTTPException, status
|
|
2
|
+
from fastapi.security import APIKeyHeader
|
|
3
|
+
|
|
4
|
+
from fred.rest.settings import FRD_RESTAPI_TOKEN
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
async def verify_key(
|
|
8
|
+
api_key_header: str = Security(
|
|
9
|
+
APIKeyHeader(
|
|
10
|
+
name="X-API-Key",
|
|
11
|
+
auto_error=False
|
|
12
|
+
)
|
|
13
|
+
),
|
|
14
|
+
):
|
|
15
|
+
"""
|
|
16
|
+
Verify the provided API key against the expected token.
|
|
17
|
+
Raises an HTTPException if the key is invalid or missing.
|
|
18
|
+
"""
|
|
19
|
+
if api_key_header != FRD_RESTAPI_TOKEN:
|
|
20
|
+
raise HTTPException(
|
|
21
|
+
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
22
|
+
detail="Invalid or missing API Key",
|
|
23
|
+
)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
from fred.rest.router.catalog.interface import RouterCatalogInterface
|
|
5
|
+
from fred.rest.settings import (
|
|
6
|
+
FRD_RESTAPI_ROUTERCATALOG_CLASSPATH,
|
|
7
|
+
FRD_RESTAPI_ROUTERCATALOG_CLASSNAME,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
@dataclass(frozen=True, slots=True)
|
|
11
|
+
class ServerRouterCatalogConfig:
|
|
12
|
+
classname: str
|
|
13
|
+
classpath: str
|
|
14
|
+
|
|
15
|
+
@classmethod
|
|
16
|
+
def auto(cls, classname: Optional[str] = None, classpath: Optional[str] = None) -> "ServerRouterCatalogConfig":
|
|
17
|
+
return cls(
|
|
18
|
+
classname=classname or FRD_RESTAPI_ROUTERCATALOG_CLASSNAME,
|
|
19
|
+
classpath=classpath or FRD_RESTAPI_ROUTERCATALOG_CLASSPATH,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
@property
|
|
23
|
+
def catalog(self) -> type[RouterCatalogInterface]:
|
|
24
|
+
import importlib
|
|
25
|
+
|
|
26
|
+
module = importlib.import_module(self.classpath)
|
|
27
|
+
catalog_class = getattr(module, self.classname, None)
|
|
28
|
+
if catalog_class is None:
|
|
29
|
+
raise ImportError(f"Could not find class '{self.classname}' in module '{self.classpath}'")
|
|
30
|
+
if not issubclass(catalog_class, RouterCatalogInterface):
|
|
31
|
+
raise TypeError(f"Class '{self.classname}' is not a subclass of RouterCatalogInterface")
|
|
32
|
+
return catalog_class
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from fred.rest.router.catalog.default.catalog import RouterCatalog
|
|
2
|
+
from fred.settings import logger_manager
|
|
3
|
+
|
|
4
|
+
logger = logger_manager.get_logger(name=__name__)
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
logger.warning(
|
|
8
|
+
"You are using the default router catalog intended for demonstration purposes only. "
|
|
9
|
+
"For production use, please implement a custom router catalog."
|
|
10
|
+
)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from fred.rest.router.interface import RouterInterfaceMixin
|
|
2
|
+
from fred.rest.router.endpoint import RouterEndpointAnnotation
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class RouterBaseMixin(RouterInterfaceMixin):
|
|
6
|
+
|
|
7
|
+
@RouterEndpointAnnotation.set(
|
|
8
|
+
path="/",
|
|
9
|
+
methods=["GET"],
|
|
10
|
+
summary="Base endpoint",
|
|
11
|
+
description="A simple base endpoint to check service availability."
|
|
12
|
+
)
|
|
13
|
+
def base(self, include_telemetry: bool = False, **kwargs) -> dict:
|
|
14
|
+
if include_telemetry:
|
|
15
|
+
from fred.utils.runtime import RuntimeProfilingSnapshot
|
|
16
|
+
kwargs["telemetry"] = RuntimeProfilingSnapshot.auto().to_dict()
|
|
17
|
+
return {
|
|
18
|
+
"ok": True,
|
|
19
|
+
**kwargs
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@RouterEndpointAnnotation.set(
|
|
23
|
+
path="/passthrough",
|
|
24
|
+
methods=["POST"],
|
|
25
|
+
summary="Passthrough POST endpoint",
|
|
26
|
+
description="An endpoint that returns all received parameters.",
|
|
27
|
+
)
|
|
28
|
+
def passthrough(self, **kwargs) -> dict:
|
|
29
|
+
return kwargs
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
from fred.rest.router.interface import RouterInterfaceMixin
|
|
5
|
+
from fred.rest.router.endpoint import RouterEndpointAnnotation
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class RouterExampleMixin(RouterInterfaceMixin):
|
|
9
|
+
|
|
10
|
+
@RouterEndpointAnnotation.set(
|
|
11
|
+
path="/ping",
|
|
12
|
+
methods=["GET"],
|
|
13
|
+
summary="Ping endpoint",
|
|
14
|
+
description="A simple ping endpoint to check service availability.",
|
|
15
|
+
)
|
|
16
|
+
def ping(self, pong: Optional[str] = None, **kwargs) -> dict:
|
|
17
|
+
from fred.utils.dateops import datetime_utcnow
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
"ping_time": datetime_utcnow().isoformat(),
|
|
21
|
+
"ping_response": pong or "pong",
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@RouterEndpointAnnotation.set(
|
|
25
|
+
path="/passthrough",
|
|
26
|
+
methods=["GET"],
|
|
27
|
+
summary="Passthrough GET endpoint",
|
|
28
|
+
description="An endpoint that returns all received parameters.",
|
|
29
|
+
)
|
|
30
|
+
def passthrough(self, **kwargs) -> dict:
|
|
31
|
+
return kwargs
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import enum
|
|
2
|
+
|
|
3
|
+
from fred.rest.router.config import RouterConfig
|
|
4
|
+
from fred.rest.router.catalog.default._base import RouterBaseMixin
|
|
5
|
+
from fred.rest.router.catalog.default._example import RouterExampleMixin
|
|
6
|
+
|
|
7
|
+
from fred.rest.router.catalog.interface import RouterCatalogInterface
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class RouterCatalog(RouterCatalogInterface, enum.Enum):
|
|
11
|
+
BASE = RouterConfig.auto(prefix="")(apply=RouterBaseMixin)
|
|
12
|
+
EXAMPLE = RouterConfig.auto(prefix="/example")(apply=RouterExampleMixin)
|
|
13
|
+
|
|
14
|
+
def get_kwargs(self) -> dict:
|
|
15
|
+
match self:
|
|
16
|
+
case RouterCatalog.EXAMPLE:
|
|
17
|
+
# Disable the backend for the example router
|
|
18
|
+
return {"disregard_backend": True}
|
|
19
|
+
case _:
|
|
20
|
+
return {}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from fred.rest.router.interface import RouterInterface
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class RouterCatalogInterface:
|
|
5
|
+
|
|
6
|
+
def auto(self, **kwargs) -> RouterInterface:
|
|
7
|
+
return self.value.reference.auto(**kwargs)
|
|
8
|
+
|
|
9
|
+
def get_kwargs(self) -> dict:
|
|
10
|
+
# This method can be overridden to provide specific kwargs for router initialization
|
|
11
|
+
return {}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
from fred.rest.router.interface import RouterInterface, RouterInterfaceMixin
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@dataclass(frozen=True, slots=True)
|
|
7
|
+
class RouterConfig:
|
|
8
|
+
prefix: str
|
|
9
|
+
other: dict
|
|
10
|
+
|
|
11
|
+
@classmethod
|
|
12
|
+
def auto(cls, prefix: str = "", **kwargs) -> "RouterConfig":
|
|
13
|
+
return cls(
|
|
14
|
+
prefix=prefix,
|
|
15
|
+
other=kwargs,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
def get_applied_configs(self, router_class: type[RouterInterface]) -> "AppliedRouterConfig":
|
|
19
|
+
return AppliedRouterConfig(
|
|
20
|
+
reference=router_class,
|
|
21
|
+
config=self,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
def __call__(self, apply: type[RouterInterfaceMixin]) -> "AppliedRouterConfig":
|
|
25
|
+
router_classname = f"Router{apply.__name__}"
|
|
26
|
+
return self.get_applied_configs(
|
|
27
|
+
router_class=type(router_classname, (RouterInterface, apply, ), {})
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
def get_configs(self) -> dict:
|
|
31
|
+
return {
|
|
32
|
+
"prefix": self.prefix,
|
|
33
|
+
**self.other,
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass(frozen=True, slots=True)
|
|
38
|
+
class AppliedRouterConfig:
|
|
39
|
+
reference: type[RouterInterface]
|
|
40
|
+
config: RouterConfig
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from dataclasses import dataclass, field
|
|
3
|
+
from typing import Callable, Optional
|
|
4
|
+
|
|
5
|
+
from fastapi import Request
|
|
6
|
+
|
|
7
|
+
from fred.settings import logger_manager
|
|
8
|
+
|
|
9
|
+
logger = logger_manager.get_logger(name=__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass(frozen=True, slots=True)
|
|
13
|
+
class RouterEndpointConfig:
|
|
14
|
+
path: Optional[str] = None
|
|
15
|
+
methods: list[str] = field(default_factory=lambda: ["GET"])
|
|
16
|
+
configs: dict = field(default_factory=dict)
|
|
17
|
+
|
|
18
|
+
@classmethod
|
|
19
|
+
def auto(cls, **kwargs) -> "RouterEndpointConfig":
|
|
20
|
+
return cls(
|
|
21
|
+
path=kwargs.pop("path", None),
|
|
22
|
+
methods=(
|
|
23
|
+
kwargs.pop("methods", None)
|
|
24
|
+
or ["GET"]
|
|
25
|
+
),
|
|
26
|
+
configs=kwargs
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass(frozen=True, slots=False)
|
|
31
|
+
class RouterEndpoint:
|
|
32
|
+
function: Callable
|
|
33
|
+
configs: RouterEndpointConfig
|
|
34
|
+
|
|
35
|
+
def __call__(self, *args, **kwargs):
|
|
36
|
+
return self.function(*args, **kwargs)
|
|
37
|
+
|
|
38
|
+
def get_path(self, overwrite: Optional[str] = None) -> str:
|
|
39
|
+
fname = self.function.__name__
|
|
40
|
+
return (
|
|
41
|
+
overwrite
|
|
42
|
+
or self.configs.path
|
|
43
|
+
or logger.debug(f"Missing 'path' definition, defaulting to function name: {fname}")
|
|
44
|
+
or os.path.join("/", fname)
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
def route_config(self, path: Optional[str] = None) -> dict:
|
|
48
|
+
return {
|
|
49
|
+
"path": self.get_path(overwrite=path),
|
|
50
|
+
"methods": self.configs.methods,
|
|
51
|
+
**self.configs.configs,
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
# Here are a couple of reference to understand why this class is needed:
|
|
55
|
+
# https://stackoverflow.com/questions/2365701/decorating-class-methods-how-to-pass-the-instance-to-the-decorator/3296318#3296318
|
|
56
|
+
# https://stackoverflow.com/questions/75409483/why-do-i-get-missing-required-argument-self-when-using-a-decorator-written-as
|
|
57
|
+
@dataclass(frozen=True, slots=True)
|
|
58
|
+
class RouterEndpointAnnotation(RouterEndpoint):
|
|
59
|
+
|
|
60
|
+
@classmethod
|
|
61
|
+
def set(cls, **kwargs) -> Callable:
|
|
62
|
+
config = RouterEndpointConfig.auto(**kwargs)
|
|
63
|
+
return lambda function: cls(function=function, configs=config)
|
|
64
|
+
|
|
65
|
+
def __get__(self, other, other_type):
|
|
66
|
+
# Create a partial function that binds the instance (other) to the method.
|
|
67
|
+
# This method was originally implemented using the following approaches:
|
|
68
|
+
# - function = functools.partial(self.function, other)
|
|
69
|
+
# - function = lambda payload: self.function(other, **payload)
|
|
70
|
+
# - function = functools.wraps(self.function)(lambda *args, **kwargs: self.function(other, *args, **kwargs))
|
|
71
|
+
# However, these approaches did not work well with FastAPI's async handling and request parsing
|
|
72
|
+
# since the dynamic lambda attributes were not being recognized properly by FastAPI.
|
|
73
|
+
# The current implementation defines an async closure that correctly calls the inner function
|
|
74
|
+
# and retrieves the parameters directly from the Request object.
|
|
75
|
+
# For more info on how to use the request object, see:
|
|
76
|
+
# - https://fastapi.tiangolo.com/advanced/using-request-directly/#use-the-request-object-directly
|
|
77
|
+
# - https://stackoverflow.com/questions/67636088/how-to-access-request-object-in-router-function-using-fastapi
|
|
78
|
+
# - https://www.starlette.dev/requests/
|
|
79
|
+
async def closure(request: Request):
|
|
80
|
+
params = {
|
|
81
|
+
**request.headers,
|
|
82
|
+
**request.path_params,
|
|
83
|
+
**request.query_params,
|
|
84
|
+
}
|
|
85
|
+
try:
|
|
86
|
+
if request.method in ("POST", "PUT", "PATCH"):
|
|
87
|
+
params.update(await request.json())
|
|
88
|
+
except Exception:
|
|
89
|
+
pass
|
|
90
|
+
return self.function(other, **params)
|
|
91
|
+
return RouterEndpoint(
|
|
92
|
+
function=closure,
|
|
93
|
+
configs=self.configs
|
|
94
|
+
)
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Callable, Optional
|
|
3
|
+
|
|
4
|
+
from fred.worker.runner.backend import RunnerBackend
|
|
5
|
+
from fred.worker.runner.settings import FRD_RUNNER_BACKEND
|
|
6
|
+
from fred.rest.router.endpoint import RouterEndpoint
|
|
7
|
+
from fred.settings import logger_manager
|
|
8
|
+
|
|
9
|
+
from fastapi import APIRouter
|
|
10
|
+
|
|
11
|
+
logger = logger_manager.get_logger(name=__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class RouterInterfaceMixin:
|
|
15
|
+
"""Base class for router interfaces that require a backend service."""
|
|
16
|
+
runner_backend: RunnerBackend
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass(frozen=True, slots=True)
|
|
20
|
+
class RouterInterface(RouterInterfaceMixin):
|
|
21
|
+
router: APIRouter
|
|
22
|
+
|
|
23
|
+
@classmethod
|
|
24
|
+
def set_backend(
|
|
25
|
+
cls,
|
|
26
|
+
service_name: Optional[str] = None,
|
|
27
|
+
disable_runner_reuse: bool = False,
|
|
28
|
+
**kwargs
|
|
29
|
+
) -> type["RouterInterface"]:
|
|
30
|
+
runner_backend = kwargs.pop("runner_backend", None)
|
|
31
|
+
if not disable_runner_reuse and runner_backend is None:
|
|
32
|
+
logger.warning(
|
|
33
|
+
"Runner reuse is enabled but no existing backend was provided; "
|
|
34
|
+
"a new backend will be created."
|
|
35
|
+
)
|
|
36
|
+
disable_runner_reuse = True
|
|
37
|
+
if disable_runner_reuse:
|
|
38
|
+
runner_backend = RunnerBackend.auto(
|
|
39
|
+
service_name=service_name or FRD_RUNNER_BACKEND,
|
|
40
|
+
**kwargs,
|
|
41
|
+
)
|
|
42
|
+
if runner_backend is None:
|
|
43
|
+
raise ValueError("Runner backend could not be determined or created.")
|
|
44
|
+
return type(
|
|
45
|
+
"RouterInterfaceWithBackend",
|
|
46
|
+
(cls, ),
|
|
47
|
+
{
|
|
48
|
+
"runner_backend": runner_backend
|
|
49
|
+
}
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
@classmethod
|
|
53
|
+
def auto(
|
|
54
|
+
cls,
|
|
55
|
+
service_name: Optional[str] = None,
|
|
56
|
+
router: Optional[APIRouter] = None,
|
|
57
|
+
disregard_backend: bool = False,
|
|
58
|
+
disregard_endpoint_setup: bool = False,
|
|
59
|
+
**kwargs,
|
|
60
|
+
) -> "RouterInterface":
|
|
61
|
+
subcls = cls if disregard_backend else cls.set_backend(
|
|
62
|
+
service_name=service_name,
|
|
63
|
+
runner_backend=getattr(cls, "runner_backend", None),
|
|
64
|
+
**kwargs
|
|
65
|
+
)
|
|
66
|
+
instance = subcls(router=router or APIRouter())
|
|
67
|
+
if disregard_endpoint_setup:
|
|
68
|
+
return instance
|
|
69
|
+
for endpoint in subcls.endpoint_definitions():
|
|
70
|
+
instance.register_endpoint(endpoint)
|
|
71
|
+
return instance
|
|
72
|
+
|
|
73
|
+
def register_endpoint(self, endpoint: RouterEndpoint, path: Optional[str] = None):
|
|
74
|
+
route_config = endpoint.route_config(path=path)
|
|
75
|
+
self.router.add_api_route(endpoint=endpoint.function, **route_config)
|
|
76
|
+
|
|
77
|
+
@classmethod
|
|
78
|
+
def endpoint_definitions(cls) -> list[RouterEndpoint]:
|
|
79
|
+
return [
|
|
80
|
+
obj
|
|
81
|
+
for attr in dir(cls)
|
|
82
|
+
if isinstance((obj := getattr(cls, attr)), RouterEndpoint)
|
|
83
|
+
]
|
|
84
|
+
|
|
85
|
+
@classmethod
|
|
86
|
+
def endpoint_definition_mapping(cls) -> dict[str, RouterEndpoint]:
|
|
87
|
+
return {
|
|
88
|
+
endpoint.get_path(): endpoint
|
|
89
|
+
for endpoint in cls.endpoint_definitions()
|
|
90
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
from fastapi import FastAPI, Depends
|
|
5
|
+
|
|
6
|
+
from fred.settings import (
|
|
7
|
+
get_environ_variable,
|
|
8
|
+
logger_manager,
|
|
9
|
+
)
|
|
10
|
+
from fred.rest.settings import (
|
|
11
|
+
FRD_RESTAPI_HOST,
|
|
12
|
+
FRD_RESTAPI_PORT,
|
|
13
|
+
FRD_RESTAPI_LOGLEVEL,
|
|
14
|
+
FRD_RESTAPI_DISABLE_AUTH,
|
|
15
|
+
)
|
|
16
|
+
from fred.rest.config import ServerRouterCatalogConfig
|
|
17
|
+
from fred.rest.auth import verify_key
|
|
18
|
+
|
|
19
|
+
logger = logger_manager.get_logger(name=__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass(frozen=True, slots=True)
|
|
23
|
+
class FredServer:
|
|
24
|
+
app: FastAPI
|
|
25
|
+
include_routers: list[str]
|
|
26
|
+
exclude_routers: list[str]
|
|
27
|
+
router_classname: Optional[str] = None
|
|
28
|
+
router_classpath: Optional[str] = None
|
|
29
|
+
|
|
30
|
+
@classmethod
|
|
31
|
+
def auto(cls, **kwargs) -> "FredServer":
|
|
32
|
+
# Include routers by checking on keyword argument or environment variable
|
|
33
|
+
include_routers = kwargs.pop("include_routers", None) or get_environ_variable(
|
|
34
|
+
"FRD_RESTAPI_INCLUDE_ROUTERS",
|
|
35
|
+
default=""
|
|
36
|
+
)
|
|
37
|
+
if isinstance(include_routers, str):
|
|
38
|
+
include_routers = [
|
|
39
|
+
name.upper()
|
|
40
|
+
for router in include_routers.split(";")
|
|
41
|
+
if (name := router.strip())
|
|
42
|
+
]
|
|
43
|
+
# Exclude routers by checking on keyword argument or environment variable
|
|
44
|
+
exclude_routers = kwargs.pop("exclude_routers", None) or get_environ_variable(
|
|
45
|
+
"FRD_RESTAPI_EXCLUDE_ROUTERS",
|
|
46
|
+
default=""
|
|
47
|
+
)
|
|
48
|
+
if isinstance(exclude_routers, str):
|
|
49
|
+
exclude_routers = [
|
|
50
|
+
name.upper()
|
|
51
|
+
for router in exclude_routers.split(";")
|
|
52
|
+
if (name := router.strip())
|
|
53
|
+
]
|
|
54
|
+
# Auth dependencies setup
|
|
55
|
+
auth_dependency = [] if FRD_RESTAPI_DISABLE_AUTH else [
|
|
56
|
+
Depends(verify_key),
|
|
57
|
+
]
|
|
58
|
+
kwargs["dependencies"] = kwargs.get("dependencies", []) + auth_dependency
|
|
59
|
+
# Create FastAPI app instance
|
|
60
|
+
app_instance = FastAPI(**kwargs)
|
|
61
|
+
router_classname = kwargs.pop("router_classname", None)
|
|
62
|
+
router_classpath = kwargs.pop("router_classpath", None)
|
|
63
|
+
return cls(
|
|
64
|
+
app=app_instance,
|
|
65
|
+
include_routers=include_routers,
|
|
66
|
+
exclude_routers=exclude_routers,
|
|
67
|
+
router_classname=router_classname,
|
|
68
|
+
router_classpath=router_classpath,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
def __post_init__(self):
|
|
72
|
+
logger.info("Attempting to register routers...")
|
|
73
|
+
logger.info("Included routers candidates: %s", self.include_routers or "ALL")
|
|
74
|
+
logger.info("Excluded routers candidates: %s", self.exclude_routers or "NONE")
|
|
75
|
+
srcc = ServerRouterCatalogConfig.auto(
|
|
76
|
+
classname=self.router_classname,
|
|
77
|
+
classpath=self.router_classpath,
|
|
78
|
+
)
|
|
79
|
+
for router_spec in srcc.catalog:
|
|
80
|
+
name = router_spec.name.upper()
|
|
81
|
+
if self.include_routers and name not in self.include_routers:
|
|
82
|
+
logger.info(f"Skipping router '{name}' as it's not in the include list.")
|
|
83
|
+
continue
|
|
84
|
+
if self.exclude_routers and name in self.exclude_routers:
|
|
85
|
+
logger.info(f"Skipping router '{name}' as it's in the exclude list.")
|
|
86
|
+
continue
|
|
87
|
+
logger.info(f"Registering router '{name}'.")
|
|
88
|
+
kwargs = router_spec.get_kwargs()
|
|
89
|
+
router_instance = router_spec.value.reference.auto(**kwargs)
|
|
90
|
+
router_configs = router_spec.value.config.get_configs()
|
|
91
|
+
# Register the router in the FastAPI app
|
|
92
|
+
self.app.include_router(router_instance.router, **router_configs)
|
|
93
|
+
|
|
94
|
+
def start(self, **kwargs):
|
|
95
|
+
import uvicorn
|
|
96
|
+
|
|
97
|
+
server_kwargs = {
|
|
98
|
+
"host": kwargs.pop("host", FRD_RESTAPI_HOST),
|
|
99
|
+
"port": int(kwargs.pop("port", FRD_RESTAPI_PORT)),
|
|
100
|
+
"log_level": FRD_RESTAPI_LOGLEVEL,
|
|
101
|
+
**kwargs,
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
uvicorn.run(self.app, **server_kwargs)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from fred.settings import get_environ_variable, logger_manager
|
|
2
|
+
|
|
3
|
+
logger = logger_manager.get_logger(name=__name__)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
FRD_RESTAPI_HOST = get_environ_variable(
|
|
7
|
+
"FRD_RESTAPI_HOST",
|
|
8
|
+
default="0.0.0.0"
|
|
9
|
+
)
|
|
10
|
+
FRD_RESTAPI_PORT = int(get_environ_variable(
|
|
11
|
+
"FRD_RESTAPI_PORT",
|
|
12
|
+
default=8000
|
|
13
|
+
))
|
|
14
|
+
|
|
15
|
+
FRD_RESTAPI_LOGLEVEL = get_environ_variable(
|
|
16
|
+
"FRD_RESTAPI_LOGLEVEL",
|
|
17
|
+
default="info"
|
|
18
|
+
).lower()
|
|
19
|
+
|
|
20
|
+
FRD_RESTAPI_DISABLE_AUTH = get_environ_variable(
|
|
21
|
+
"FRD_RESTAPI_DISABLE_AUTH",
|
|
22
|
+
default="false"
|
|
23
|
+
).lower() in ("1", "true", "yes", "on")
|
|
24
|
+
|
|
25
|
+
FRD_RESTAPI_TOKEN = get_environ_variable(
|
|
26
|
+
"FRD_RESTAPI_TOKEN",
|
|
27
|
+
default=None
|
|
28
|
+
)
|
|
29
|
+
if not FRD_RESTAPI_TOKEN:
|
|
30
|
+
logger.warning("FRD_RESTAPI_TOKEN not found in environment; using default token 'changeme'.")
|
|
31
|
+
FRD_RESTAPI_TOKEN = "changeme"
|
|
32
|
+
|
|
33
|
+
FRD_RESTAPI_EXCLUDE_BUILTIN_ROUTERS = get_environ_variable(
|
|
34
|
+
"FRD_RESTAPI_EXCLUDE_BUILTIN_ROUTERS",
|
|
35
|
+
default="false",
|
|
36
|
+
).lower() in ("1", "true", "yes", "on")
|
|
37
|
+
|
|
38
|
+
FRD_RESTAPI_ROUTERCATALOG_CLASSNAME = get_environ_variable(
|
|
39
|
+
"FRD_RESTAPI_ROUTERCATALOG_CLASSNAME",
|
|
40
|
+
default="RouterCatalog",
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
FRD_RESTAPI_ROUTERCATALOG_CLASSPATH = get_environ_variable(
|
|
44
|
+
"FRD_RESTAPI_ROUTERCATALOG_CLASSPATH",
|
|
45
|
+
default="fred.rest.router.catalog.default",
|
|
46
|
+
)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.56.0
|
|
File without changes
|
|
File without changes
|
|
@@ -58,6 +58,21 @@ src/main/fred/monad/__init__.py
|
|
|
58
58
|
src/main/fred/monad/_either.py
|
|
59
59
|
src/main/fred/monad/catalog.py
|
|
60
60
|
src/main/fred/monad/interface.py
|
|
61
|
+
src/main/fred/rest/__init__.py
|
|
62
|
+
src/main/fred/rest/auth.py
|
|
63
|
+
src/main/fred/rest/config.py
|
|
64
|
+
src/main/fred/rest/server.py
|
|
65
|
+
src/main/fred/rest/settings.py
|
|
66
|
+
src/main/fred/rest/router/__init__.py
|
|
67
|
+
src/main/fred/rest/router/config.py
|
|
68
|
+
src/main/fred/rest/router/endpoint.py
|
|
69
|
+
src/main/fred/rest/router/interface.py
|
|
70
|
+
src/main/fred/rest/router/catalog/__init__.py
|
|
71
|
+
src/main/fred/rest/router/catalog/interface.py
|
|
72
|
+
src/main/fred/rest/router/catalog/default/__init__.py
|
|
73
|
+
src/main/fred/rest/router/catalog/default/_base.py
|
|
74
|
+
src/main/fred/rest/router/catalog/default/_example.py
|
|
75
|
+
src/main/fred/rest/router/catalog/default/catalog.py
|
|
61
76
|
src/main/fred/utils/__init__.py
|
|
62
77
|
src/main/fred/utils/dateops.py
|
|
63
78
|
src/main/fred/utils/imops.py
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
from fred.version import version
|
|
2
|
-
from fred.settings import logger_manager
|
|
3
|
-
from fred.cli.interface import AbstractCLI
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
logger = logger_manager.get_logger(name=__name__)
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class CLIExtensionGroups:
|
|
10
|
-
"""CLI Extensions providing access to various integrations by following a lazy loading pattern."""
|
|
11
|
-
|
|
12
|
-
@property
|
|
13
|
-
def databricks(self):
|
|
14
|
-
from fred.integrations.databricks.cli_ext import DatabricksExt
|
|
15
|
-
return DatabricksExt()
|
|
16
|
-
|
|
17
|
-
@property
|
|
18
|
-
def runpod(self):
|
|
19
|
-
from fred.integrations.runpod.cli_ext import RunPodExt
|
|
20
|
-
return RunPodExt()
|
|
21
|
-
|
|
22
|
-
@property
|
|
23
|
-
def runner_server(self):
|
|
24
|
-
from fred.worker.runner.rest.cli_ext import RunnerServerExt
|
|
25
|
-
return RunnerServerExt()
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
class CLI(AbstractCLI, CLIExtensionGroups):
|
|
29
|
-
|
|
30
|
-
def version(self) -> str:
|
|
31
|
-
return version.value
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
0.55.0
|
|
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
|
{fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/dao/service/_minio/policy/templates/public_ro.json
RENAMED
|
File without changes
|
{fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/dao/service/_minio/policy/templates/public_rw.json
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/integrations/databricks/runtimes/16.4LTS.json
RENAMED
|
File without changes
|
{fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/integrations/databricks/runtimes/__init__.py
RENAMED
|
File without changes
|
{fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/integrations/databricks/runtimes/scanner.py
RENAMED
|
File without changes
|
|
File without changes
|
{fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/integrations/databricks/wrappers/__init__.py
RENAMED
|
File without changes
|
{fred_oss-0.55.0 → fred_oss-0.56.0}/src/main/fred/integrations/databricks/wrappers/dbutils.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
|
{fred_oss-0.55.0/src/main/fred/utils → fred_oss-0.56.0/src/main/fred/rest/router}/__init__.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
|
|
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
|