fred-oss 0.14.0__tar.gz → 0.16.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 (65) hide show
  1. {fred_oss-0.14.0/src/main/fred_oss.egg-info → fred_oss-0.16.0}/PKG-INFO +1 -1
  2. fred_oss-0.16.0/src/main/fred/dao/__init__.py +11 -0
  3. fred_oss-0.16.0/src/main/fred/dao/comp/_keyval.py +76 -0
  4. fred_oss-0.16.0/src/main/fred/dao/comp/_queue.py +79 -0
  5. fred_oss-0.16.0/src/main/fred/dao/comp/catalog.py +89 -0
  6. fred_oss-0.16.0/src/main/fred/dao/comp/interface.py +59 -0
  7. fred_oss-0.16.0/src/main/fred/dao/service/_redis.py +25 -0
  8. fred_oss-0.16.0/src/main/fred/dao/service/catalog.py +36 -0
  9. fred_oss-0.16.0/src/main/fred/dao/service/interface.py +54 -0
  10. fred_oss-0.16.0/src/main/fred/dao/service/utils.py +37 -0
  11. fred_oss-0.16.0/src/main/fred/version +1 -0
  12. fred_oss-0.16.0/src/main/fred/worker/runner/rest/__init__.py +0 -0
  13. fred_oss-0.16.0/src/main/fred/worker/runner/rest/routers/__init__.py +0 -0
  14. {fred_oss-0.14.0 → fred_oss-0.16.0/src/main/fred_oss.egg-info}/PKG-INFO +1 -1
  15. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred_oss.egg-info/SOURCES.txt +11 -0
  16. fred_oss-0.14.0/src/main/fred/version +0 -1
  17. {fred_oss-0.14.0 → fred_oss-0.16.0}/MANIFEST.in +0 -0
  18. {fred_oss-0.14.0 → fred_oss-0.16.0}/NOTICE.txt +0 -0
  19. {fred_oss-0.14.0 → fred_oss-0.16.0}/README.md +0 -0
  20. {fred_oss-0.14.0 → fred_oss-0.16.0}/requirements.txt +0 -0
  21. {fred_oss-0.14.0 → fred_oss-0.16.0}/setup.cfg +0 -0
  22. {fred_oss-0.14.0 → fred_oss-0.16.0}/setup.py +0 -0
  23. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/cli/__init__.py +0 -0
  24. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/cli/__main__.py +0 -0
  25. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/cli/interface.py +0 -0
  26. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/cli/main.py +0 -0
  27. {fred_oss-0.14.0/src/main/fred/integrations/databricks/runtimes → fred_oss-0.16.0/src/main/fred/dao/comp}/__init__.py +0 -0
  28. {fred_oss-0.14.0/src/main/fred/integrations/databricks/wrappers → fred_oss-0.16.0/src/main/fred/dao/service}/__init__.py +0 -0
  29. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/integrations/databricks/__init__.py +0 -0
  30. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/integrations/databricks/cli_ext.py +0 -0
  31. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/integrations/databricks/runtime.py +0 -0
  32. {fred_oss-0.14.0/src/main/fred/utils → fred_oss-0.16.0/src/main/fred/integrations/databricks/runtimes}/__init__.py +0 -0
  33. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/integrations/databricks/runtimes/scanner.py +0 -0
  34. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/integrations/databricks/runtimes/sync.py +0 -0
  35. {fred_oss-0.14.0/src/main/fred/worker/runner/plugins → fred_oss-0.16.0/src/main/fred/integrations/databricks/wrappers}/__init__.py +0 -0
  36. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/integrations/databricks/wrappers/dbutils.py +0 -0
  37. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/integrations/runpod/__init__.py +0 -0
  38. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/integrations/runpod/cli_ext.py +0 -0
  39. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/integrations/runpod/helper.py +0 -0
  40. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/maturity.py +0 -0
  41. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/settings.py +0 -0
  42. {fred_oss-0.14.0/src/main/fred/worker/runner/rest → fred_oss-0.16.0/src/main/fred/utils}/__init__.py +0 -0
  43. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/utils/dateops.py +0 -0
  44. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/utils/runtime.py +0 -0
  45. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/version.py +0 -0
  46. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/worker/__init__.py +0 -0
  47. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/worker/interface.py +0 -0
  48. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/worker/runner/__init__.py +0 -0
  49. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/worker/runner/client.py +0 -0
  50. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/worker/runner/handler.py +0 -0
  51. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/worker/runner/info.py +0 -0
  52. {fred_oss-0.14.0/src/main/fred/worker/runner/rest/routers → fred_oss-0.16.0/src/main/fred/worker/runner/plugins}/__init__.py +0 -0
  53. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/worker/runner/plugins/_local.py +0 -0
  54. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/worker/runner/plugins/catalog.py +0 -0
  55. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/worker/runner/plugins/interface.py +0 -0
  56. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/worker/runner/rest/cli_ext.py +0 -0
  57. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/worker/runner/rest/routers/_runner.py +0 -0
  58. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/worker/runner/rest/routers/catalog.py +0 -0
  59. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/worker/runner/rest/routers/interface.py +0 -0
  60. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/worker/runner/rest/server.py +0 -0
  61. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred/worker/runner/utils.py +0 -0
  62. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred_oss.egg-info/dependency_links.txt +0 -0
  63. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred_oss.egg-info/entry_points.txt +0 -0
  64. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred_oss.egg-info/requires.txt +0 -0
  65. {fred_oss-0.14.0 → fred_oss-0.16.0}/src/main/fred_oss.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fred-oss
3
- Version: 0.14.0
3
+ Version: 0.16.0
4
4
  Summary: FREDOSS
5
5
  Home-page: https://fred.fahera.mx
6
6
  Author: Fahera Research, Education, and Development
@@ -0,0 +1,11 @@
1
+ from fred.maturity import Maturity, MaturityLevel
2
+
3
+
4
+ module_maturity = Maturity(
5
+ level=MaturityLevel.ALPHA,
6
+ reference=__name__,
7
+ message=(
8
+ "Fred-DAO implementation is in early development "
9
+ "and therefore currently with incomplete and unstable features."
10
+ )
11
+ )
@@ -0,0 +1,76 @@
1
+ from dataclasses import dataclass
2
+ from typing import Optional
3
+
4
+ from fred.dao.service.catalog import ServiceCatalog
5
+ from fred.dao.comp.interface import ComponentInterface
6
+
7
+
8
+ @dataclass(frozen=True, slots=True)
9
+ class FredKeyVal(ComponentInterface):
10
+ """A simple key-value store implementation using a backend service.
11
+ This class provides methods to interact with a key-value store, such as setting,
12
+ getting, and deleting key-value pairs. The actual implementation of these methods
13
+ depends on the underlying service being used (e.g., Redis).
14
+ """
15
+
16
+ def set(self, key: str, value: str, **kwargs) -> None:
17
+ """Sets a key-value pair in the store.
18
+ The implementation of this method depends on the underlying service.
19
+ For example, if the service is Redis, it uses the SET command to store the
20
+ key-value pair.
21
+ Args:
22
+ key (str): The key to set.
23
+ value (str): The value to associate with the key.
24
+ **kwargs: Additional keyword arguments for setting the key-value pair,
25
+ such as expiration time.
26
+ Raises:
27
+ NotImplementedError: If the method is not implemented for the current service.
28
+ """
29
+ match self._cat:
30
+ case ServiceCatalog.REDIS:
31
+ self._srv.client.set(key, value)
32
+ expire = kwargs.get("expire")
33
+ if expire and isinstance(expire, int):
34
+ self._srv.client.expire(key, expire)
35
+ case _:
36
+ raise NotImplementedError(f"Set method not implemented for service {self._nme}")
37
+
38
+ def get(self, key: str, fail: bool = False) -> Optional[str]:
39
+ """Gets the value associated with a key from the store.
40
+ The implementation of this method depends on the underlying service.
41
+ For example, if the service is Redis, it uses the GET command to retrieve the
42
+ value associated with the key.
43
+ Args:
44
+ key (str): The key to retrieve.
45
+ fail (bool): If True, raises a KeyError if the key is not found. Defaults to False.
46
+ Returns:
47
+ Optional[str]: The value associated with the key, or None if the key is not found
48
+ and fail is False.
49
+ Raises:
50
+ KeyError: If the key is not found and fail is True.
51
+ NotImplementedError: If the method is not implemented for the current service.
52
+ """
53
+ match self._cat:
54
+ case ServiceCatalog.REDIS:
55
+ result = self._srv.client.get(key)
56
+ if result is None and fail:
57
+ raise KeyError(f"Key {key} not found.")
58
+ return result
59
+ case _:
60
+ raise NotImplementedError(f"Get method not implemented for service {self._nme}")
61
+
62
+ def delete(self, key: str) -> None:
63
+ """Deletes a key-value pair from the store.
64
+ The implementation of this method depends on the underlying service.
65
+ For example, if the service is Redis, it uses the DEL command to remove the
66
+ key-value pair.
67
+ Args:
68
+ key (str): The key to delete.
69
+ Raises:
70
+ NotImplementedError: If the method is not implemented for the current service.
71
+ """
72
+ match self._cat:
73
+ case ServiceCatalog.REDIS:
74
+ self._srv.client.delete(key)
75
+ case _:
76
+ raise NotImplementedError(f"Delete method not implemented for service {self._nme}")
@@ -0,0 +1,79 @@
1
+ from dataclasses import dataclass
2
+ from typing import Optional
3
+
4
+ from fred.dao.service.catalog import ServiceCatalog
5
+ from fred.dao.comp.interface import ComponentInterface
6
+
7
+
8
+ @dataclass(frozen=True, slots=True)
9
+ class FredQueue(ComponentInterface):
10
+ """A simple queue implementation using a backend service.
11
+ This class provides methods to interact with a queue, such as adding,
12
+ removing, and checking the size of the queue. The actual implementation
13
+ of these methods depends on the underlying service being used (e.g., Redis).
14
+ Attributes:
15
+ name: str: The name of the queue.
16
+ """
17
+ name: str
18
+
19
+ def size(self) -> int:
20
+ """Returns the number of items in the queue.
21
+ The implementation of this method depends on the underlying service.
22
+ For example, if the service is Redis, it uses the LLEN command to get the
23
+ length of the list representing the queue.
24
+ Returns:
25
+ int: The number of items in the queue.
26
+ Raises:
27
+ NotImplementedError: If the method is not implemented for the current service.
28
+ """
29
+ match self._cat:
30
+ case ServiceCatalog.REDIS:
31
+ return self._srv.client.llen(self.name)
32
+ case _:
33
+ raise NotImplementedError(f"Size method not implemented for service {self._nme}")
34
+
35
+ def clear(self) -> None:
36
+ """Clears all items from the queue.
37
+ The implementation of this method depends on the underlying service.
38
+ For example, if the service is Redis, it uses the DEL command to remove the
39
+ key representing the queue.
40
+ Raises:
41
+ NotImplementedError: If the method is not implemented for the current service.
42
+ """
43
+ match self._cat:
44
+ case ServiceCatalog.REDIS:
45
+ self._srv.client.delete(self.name)
46
+ case _:
47
+ raise NotImplementedError(f"Clear method not implemented for service {self._nme}")
48
+
49
+ def add(self, item: str) -> None:
50
+ """Adds an item to the queue.
51
+ The implementation of this method depends on the underlying service.
52
+ For example, if the service is Redis, it uses the LPUSH command to add the
53
+ item to the front of the list representing the queue.
54
+ Args:
55
+ item (str): The item to add to the queue.
56
+ Raises:
57
+ NotImplementedError: If the method is not implemented for the current service.
58
+ """
59
+ match self._cat:
60
+ case ServiceCatalog.REDIS:
61
+ self._srv.client.lpush(self.name, item)
62
+ case _:
63
+ raise NotImplementedError(f"Add method not implemented for service {self._srv._nme}")
64
+
65
+ def pop(self) -> Optional[str]:
66
+ """Removes and returns an item from the queue.
67
+ The implementation of this method depends on the underlying service.
68
+ For example, if the service is Redis, it uses the RPOP command to remove and
69
+ return the last item from the list representing the queue.
70
+ Returns:
71
+ Optional[str]: The item removed from the queue, or None if the queue is empty.
72
+ Raises:
73
+ NotImplementedError: If the method is not implemented for the current service.
74
+ """
75
+ match self._cat:
76
+ case ServiceCatalog.REDIS:
77
+ return self._srv.client.rpop(self.name)
78
+ case _:
79
+ raise NotImplementedError(f"Pop method not implemented for service {self._srv._nme}")
@@ -0,0 +1,89 @@
1
+ import enum
2
+ from functools import lru_cache
3
+ from typing import Optional
4
+
5
+ from fred.dao.comp.interface import ComponentInterface
6
+ from fred.dao.comp._queue import FredQueue
7
+ from fred.dao.comp._keyval import FredKeyVal
8
+
9
+
10
+ class _PreconfCatalogMixin:
11
+ """A mixin class to allow enum members to be called directly to create instances
12
+ of preconfigured components.
13
+ This mixin is used in conjunction with the `preconf` class method of the `CompCatalog`
14
+ enum to create a new enum with preconfigured components for a specific service."""
15
+
16
+ def __call__(self, *args, **kwargs) -> ComponentInterface:
17
+ """Create an instance of the preconfigured component. This method
18
+ allows the enum member to be called directly to instantiate the component
19
+ with any additional arguments.
20
+ Args:
21
+ *args: Positional arguments to pass to the component constructor.
22
+ **kwargs: Keyword arguments to pass to the component constructor.
23
+ Returns:
24
+ ComponentInterface: An instance of the preconfigured component.
25
+ """
26
+ return self.value(*args, **kwargs)
27
+
28
+
29
+ class CompCatalog(enum.Enum):
30
+ """An enumeration of available component types.
31
+ Each enum member corresponds to a specific component class that implements
32
+ the `ComponentInterface`. This enum provides a way to reference and create
33
+ instances of different component types in a standardized manner.
34
+ """
35
+ QUEUE = FredQueue
36
+ KEYVAL = FredKeyVal
37
+
38
+ @classmethod
39
+ def from_classname(cls, classname: str) -> "CompCatalog":
40
+ """Get enum member by component class name.
41
+ Args:
42
+ classname (str): The class name of the component.
43
+ Returns:
44
+ CompCatalog: The corresponding enum member.
45
+ Raises:
46
+ ValueError: If no matching component is found.
47
+ """
48
+ for item in cls:
49
+ if item.value.__name__ == classname:
50
+ return item
51
+ raise ValueError(f"No component found for classname: {classname}")
52
+
53
+ @classmethod
54
+ @lru_cache(maxsize=None) # TODO: Consider cache invalidation strategy if needed
55
+ def preconf(cls, srv_name: str, **kwargs) -> enum.Enum:
56
+ """Create a new Enum with preconfigured components for a specific service name.
57
+ Args:
58
+ srv_name (str): The service name to preconfigure the components with.
59
+ **kwargs: Additional keyword arguments to pass to the component constructors.
60
+ Returns:
61
+ enum.Enum: A new Enum class with preconfigured components.
62
+ """
63
+ return enum.Enum(
64
+ f"{srv_name.title()}{cls.__name__}",
65
+ {item.name: item.value.mount(srv_name=srv_name, **kwargs) for item in cls},
66
+ type=_PreconfCatalogMixin,
67
+ )
68
+
69
+ def component_cls(self) -> type[ComponentInterface]:
70
+ """Returns the class of the component associated with the enum member.
71
+ Returns:
72
+ type[ComponentInterface]: The class of the component.
73
+ """
74
+ return self.value
75
+
76
+ def auto(self, srv_name: Optional[str] = None, **kwargs) -> ComponentInterface:
77
+ """Automatically creates an instance of the component, mounting it to a service.
78
+ This method is a convenience wrapper that first mounts the component to a service
79
+ and then creates an instance of the component.
80
+ Args:
81
+ srv_name (Optional[str]): The name of the service to mount. Defaults to None.
82
+ **kwargs: Additional keyword arguments for both mounting the service and
83
+ creating the component instance. If there are specific arguments
84
+ for the service, they should be passed under the key `srv_kwargs`
85
+ as a dictionary.
86
+ Returns:
87
+ ComponentInterface: An instance of the component.
88
+ """
89
+ return self.value.auto(srv_name=srv_name, **kwargs)
@@ -0,0 +1,59 @@
1
+ from typing import Optional
2
+ from fred.dao.service.interface import ServiceInterface
3
+ from fred.dao.service.catalog import ServiceCatalog
4
+
5
+
6
+ class SrvCompanionMixin:
7
+ _srv: ServiceInterface
8
+
9
+ @classmethod
10
+ def _set_srv(cls, name: Optional[str] = None, **kwargs):
11
+ """Sets the service instance for the component class.
12
+ This method initializes the `_srv` class variable with an instance
13
+ of the service specified by `name` and any additional parameters passed via `kwargs`.
14
+ Args:
15
+ name (Optional[str]): The name of the service to set. Defaults to "REDIS".
16
+ **kwargs: Additional keyword arguments to configure the service instance.
17
+ """
18
+ cls._srv = ServiceCatalog[(name or "REDIS").upper()].auto(**kwargs)
19
+
20
+ @property
21
+ def _nme(self) -> str:
22
+ """Returns the class name of the current service instance."""
23
+ return self._srv.__class__.__name__
24
+
25
+ @property
26
+ def _cat(self) -> ServiceCatalog:
27
+ """Returns the ServiceCatalog enum member corresponding to the current service instance."""
28
+ return ServiceCatalog.from_classname(self._nme)
29
+
30
+
31
+ class ComponentInterface(SrvCompanionMixin):
32
+
33
+ @classmethod
34
+ def mount(cls, srv_name: Optional[str] = None, **kwargs) -> type["ComponentInterface"]:
35
+ """Mounts the component to a specific service instance.
36
+ This method configures the component to use a service instance
37
+ identified by `srv_name` and any additional parameters passed via `kwargs`.
38
+
39
+ Args:
40
+ srv_name (Optional[str]): The name of the service to mount. Defaults to "REDIS".
41
+ **kwargs: Additional keyword arguments to configure the service instance.
42
+ """
43
+ cls._set_srv(name=srv_name, **kwargs)
44
+ return cls
45
+
46
+ @classmethod
47
+ def auto(cls, srv_name: Optional[str] = None, **kwargs) -> "ComponentInterface":
48
+ """Automatically creates an instance of the component, mounting it to a service.
49
+ This method is a convenience wrapper that first mounts the component to a service
50
+ and then creates an instance of the component.
51
+ Args:
52
+ srv_name (Optional[str]): The name of the service to mount. Defaults to "REDIS".
53
+ **kwargs: Additional keyword arguments for both mounting the service and
54
+ creating the component instance. If there are specific arguments
55
+ for the service, they should be passed under the key `srv_kwargs`
56
+ as a dictionary.
57
+ """
58
+ srv_kwargs = kwargs.pop("srv_kwargs", {})
59
+ return cls.mount(srv_name=srv_name, **srv_kwargs)(**kwargs)
@@ -0,0 +1,25 @@
1
+ from redis import Redis, ConnectionPool
2
+
3
+ from fred.dao.service.utils import get_redis_configs_from_payload
4
+ from fred.dao.service.interface import ServiceConnectionPoolInterface, ServiceInterface
5
+
6
+
7
+ class RedisConnectionPool(ServiceConnectionPoolInterface[ConnectionPool]):
8
+
9
+ @classmethod
10
+ def _create_pool(cls, **kwargs) -> ConnectionPool:
11
+ configs = get_redis_configs_from_payload(payload=kwargs, keep=False)
12
+ return ConnectionPool(**configs)
13
+
14
+
15
+ class RedisService(ServiceInterface[Redis]):
16
+ instance: Redis
17
+
18
+ @classmethod
19
+ def _create_instance(cls, **kwargs) -> Redis:
20
+ return Redis(connection_pool=RedisConnectionPool.get_or_create_pool(**kwargs))
21
+
22
+ @classmethod
23
+ def auto(cls, **kwargs) -> "RedisService":
24
+ cls.instance = Redis(connection_pool=RedisConnectionPool.get_or_create_pool(**kwargs))
25
+ return cls(**kwargs)
@@ -0,0 +1,36 @@
1
+ import enum
2
+ from functools import lru_cache
3
+
4
+ from fred.dao.service.interface import ServiceInterface
5
+ from fred.dao.service._redis import RedisService
6
+
7
+
8
+ class ServiceCatalog(enum.Enum):
9
+ REDIS = RedisService
10
+
11
+ @classmethod
12
+ def from_classname(cls, classname: str) -> "ServiceCatalog":
13
+ for item in cls:
14
+ if item.value.__name__ == classname:
15
+ return item
16
+ raise ValueError(f"No service found for classname: {classname}")
17
+
18
+ @lru_cache(maxsize=None) # TODO: Consider cache invalidation strategy if needed
19
+ def component_catalog(self, **kwargs) -> enum.Enum:
20
+ """Get a preconfigured component catalog for this (self) service.
21
+ This method returns a new Enum with preconfigured components for the
22
+ service represented by this enum member.
23
+ Args:
24
+ **kwargs: Additional keyword arguments to pass to the component constructors.
25
+ Returns:
26
+ enum.Enum: A new Enum with preconfigured components for this service.
27
+ """
28
+ from fred.dao.comp.catalog import CompCatalog # Avoid circular import
29
+
30
+ return CompCatalog.preconf(srv_name=self.name, **kwargs)
31
+
32
+ def service_cls(self) -> type[ServiceInterface]:
33
+ return self.value
34
+
35
+ def auto(self, **kwargs) -> ServiceInterface:
36
+ return self.value.auto(**kwargs)
@@ -0,0 +1,54 @@
1
+ import uuid
2
+ import json
3
+ from functools import lru_cache
4
+ from typing import Generic, TypeVar
5
+
6
+ T = TypeVar("T")
7
+
8
+
9
+ class ServiceConnectionPoolInterface(Generic[T]):
10
+ pool_registry: dict[str, T] = {}
11
+
12
+ @classmethod
13
+ def get_pool_id(cls, **kwargs) -> str:
14
+ return str(uuid.uuid5(uuid.NAMESPACE_OID, json.dumps(kwargs, sort_keys=True)))
15
+
16
+ @classmethod
17
+ def _create_pool(cls, **kwargs) -> T:
18
+ raise NotImplementedError("This method should be implemented by subclasses.")
19
+
20
+ @classmethod
21
+ @lru_cache
22
+ def get_or_create_pool(cls, **kwargs) -> T:
23
+ pool_id = cls.get_pool_id(**kwargs)
24
+ pool = cls.pool_registry.get(pool_id)
25
+ if not pool:
26
+ pool = cls.pool_registry[pool_id] = cls._create_pool(**kwargs)
27
+ return pool
28
+
29
+
30
+ class ServiceInterface(Generic[T]):
31
+ instance: T
32
+
33
+ def __init__(self, **kwargs):
34
+ self.config = kwargs
35
+
36
+ @classmethod
37
+ def _create_instance(cls, **kwargs) -> T:
38
+ raise NotImplementedError("This method should be implemented by subclasses.")
39
+
40
+ @classmethod
41
+ def auto(cls, **kwargs) -> "ServiceInterface":
42
+ raise NotImplementedError("This method should be implemented by subclasses.")
43
+
44
+ @property
45
+ def client(self) -> T:
46
+ if not getattr(self, "instance", None):
47
+ self.instance = self._create_instance(**getattr(self, "config", {}))
48
+ return self.instance
49
+
50
+ def close(self):
51
+ # Close the instance if it has a close method.
52
+ # This method can be overridden by subclasses if needed.
53
+ if self.instance and hasattr(self.instance, "close") and callable(self.instance.close):
54
+ self.instance.close()
@@ -0,0 +1,37 @@
1
+ from fred.settings import get_environ_variable
2
+
3
+
4
+ def get_redis_configs_from_payload(
5
+ payload: dict,
6
+ keep: bool = False,
7
+ ) -> dict:
8
+ """Extract Redis configuration from the given payload dictionary.
9
+ This function looks for common Redis configuration keys in the payload
10
+ dictionary. If a key is not found, it falls back to environment variables.
11
+ Args:
12
+ payload (dict): The dictionary from which to extract Redis configuration.
13
+ keep (bool): If True, the original keys are retained in the payload. If False, they are removed.
14
+ Returns:
15
+ dict: A dictionary containing Redis configuration parameters.
16
+ """
17
+ host = port = password = db = None
18
+ for host_key in ["host", "redis_host"]:
19
+ if (host := payload.get(host_key) if keep else payload.pop(host_key, None)):
20
+ break
21
+ for port_key in ["port", "redis_port"]:
22
+ if (port := payload.get(port_key) if keep else payload.pop(port_key, None)):
23
+ break
24
+ for password_key in ["password", "redis_password"]:
25
+ if (password := payload.get(password_key) if keep else payload.pop(password_key, None)):
26
+ break
27
+ for db_key in ["db", "redis_db"]:
28
+ if (db := payload.get(db_key) if keep else payload.pop(db_key, None)):
29
+ break
30
+ return {
31
+ "host": host or get_environ_variable(name="REDIS_HOST", default="localhost"),
32
+ "port": int(port or get_environ_variable(name="REDIS_PORT", default=6379)),
33
+ "password": password or get_environ_variable(name="REDIS_PASSWORD", default=None),
34
+ "db": int(db or get_environ_variable(name="REDIS_DB", default=0)),
35
+ "decode_responses": True,
36
+ **(payload.get("redis_configs", {}) if keep else payload.pop("redis_configs", {})),
37
+ }
@@ -0,0 +1 @@
1
+ 0.16.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fred-oss
3
- Version: 0.14.0
3
+ Version: 0.16.0
4
4
  Summary: FREDOSS
5
5
  Home-page: https://fred.fahera.mx
6
6
  Author: Fahera Research, Education, and Development
@@ -11,6 +11,17 @@ src/main/fred/cli/__init__.py
11
11
  src/main/fred/cli/__main__.py
12
12
  src/main/fred/cli/interface.py
13
13
  src/main/fred/cli/main.py
14
+ src/main/fred/dao/__init__.py
15
+ src/main/fred/dao/comp/__init__.py
16
+ src/main/fred/dao/comp/_keyval.py
17
+ src/main/fred/dao/comp/_queue.py
18
+ src/main/fred/dao/comp/catalog.py
19
+ src/main/fred/dao/comp/interface.py
20
+ src/main/fred/dao/service/__init__.py
21
+ src/main/fred/dao/service/_redis.py
22
+ src/main/fred/dao/service/catalog.py
23
+ src/main/fred/dao/service/interface.py
24
+ src/main/fred/dao/service/utils.py
14
25
  src/main/fred/integrations/databricks/__init__.py
15
26
  src/main/fred/integrations/databricks/cli_ext.py
16
27
  src/main/fred/integrations/databricks/runtime.py
@@ -1 +0,0 @@
1
- 0.14.0
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes