fred-oss 0.11.0__tar.gz → 0.13.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 (47) hide show
  1. {fred_oss-0.11.0/src/main/fred_oss.egg-info → fred_oss-0.13.0}/PKG-INFO +1 -1
  2. fred_oss-0.13.0/src/main/fred/version +1 -0
  3. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred/worker/runner/client.py +2 -8
  4. fred_oss-0.13.0/src/main/fred/worker/runner/info.py +54 -0
  5. fred_oss-0.13.0/src/main/fred/worker/runner/plugins/__init__.py +0 -0
  6. fred_oss-0.13.0/src/main/fred/worker/runner/plugins/_local.py +26 -0
  7. fred_oss-0.13.0/src/main/fred/worker/runner/plugins/catalog.py +15 -0
  8. fred_oss-0.13.0/src/main/fred/worker/runner/plugins/interface.py +152 -0
  9. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred/worker/runner/utils.py +25 -0
  10. {fred_oss-0.11.0 → fred_oss-0.13.0/src/main/fred_oss.egg-info}/PKG-INFO +1 -1
  11. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred_oss.egg-info/SOURCES.txt +5 -0
  12. fred_oss-0.11.0/src/main/fred/version +0 -1
  13. {fred_oss-0.11.0 → fred_oss-0.13.0}/MANIFEST.in +0 -0
  14. {fred_oss-0.11.0 → fred_oss-0.13.0}/NOTICE.txt +0 -0
  15. {fred_oss-0.11.0 → fred_oss-0.13.0}/README.md +0 -0
  16. {fred_oss-0.11.0 → fred_oss-0.13.0}/requirements.txt +0 -0
  17. {fred_oss-0.11.0 → fred_oss-0.13.0}/setup.cfg +0 -0
  18. {fred_oss-0.11.0 → fred_oss-0.13.0}/setup.py +0 -0
  19. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred/cli/__init__.py +0 -0
  20. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred/cli/__main__.py +0 -0
  21. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred/cli/interface.py +0 -0
  22. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred/cli/main.py +0 -0
  23. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred/integrations/databricks/__init__.py +0 -0
  24. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred/integrations/databricks/cli_ext.py +0 -0
  25. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred/integrations/databricks/runtime.py +0 -0
  26. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred/integrations/databricks/runtimes/__init__.py +0 -0
  27. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred/integrations/databricks/runtimes/scanner.py +0 -0
  28. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred/integrations/databricks/runtimes/sync.py +0 -0
  29. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred/integrations/databricks/wrappers/__init__.py +0 -0
  30. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred/integrations/databricks/wrappers/dbutils.py +0 -0
  31. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred/integrations/runpod/__init__.py +0 -0
  32. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred/integrations/runpod/cli_ext.py +0 -0
  33. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred/integrations/runpod/helper.py +0 -0
  34. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred/maturity.py +0 -0
  35. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred/settings.py +0 -0
  36. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred/utils/__init__.py +0 -0
  37. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred/utils/dateops.py +0 -0
  38. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred/utils/runtime.py +0 -0
  39. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred/version.py +0 -0
  40. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred/worker/__init__.py +0 -0
  41. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred/worker/interface.py +0 -0
  42. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred/worker/runner/__init__.py +0 -0
  43. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred/worker/runner/handler.py +0 -0
  44. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred_oss.egg-info/dependency_links.txt +0 -0
  45. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred_oss.egg-info/entry_points.txt +0 -0
  46. {fred_oss-0.11.0 → fred_oss-0.13.0}/src/main/fred_oss.egg-info/requires.txt +0 -0
  47. {fred_oss-0.11.0 → fred_oss-0.13.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.11.0
3
+ Version: 0.13.0
4
4
  Summary: FREDOSS
5
5
  Home-page: https://fred.fahera.mx
6
6
  Author: Fahera Research, Education, and Development
@@ -0,0 +1 @@
1
+ 0.13.0
@@ -9,6 +9,7 @@ from fred.settings import (
9
9
  from fred.worker.runner.utils import (
10
10
  get_request_queue_name_from_payload,
11
11
  get_response_queue_name_from_payload,
12
+ get_redis_configs_from_payload,
12
13
  )
13
14
 
14
15
  from redis import Redis
@@ -24,14 +25,7 @@ class RunnerClient:
24
25
 
25
26
  @classmethod
26
27
  def auto(cls, **kwargs) -> "RunnerClient":
27
- redis_configs = {
28
- "host": kwargs.get("host") or get_environ_variable(name="REDIS_HOST", default="localhost"),
29
- "port": int(kwargs.get("port") or get_environ_variable(name="REDIS_PORT", default=6379)),
30
- "password": get_environ_variable(name="REDIS_PASSWORD", default=None),
31
- "db": int(kwargs.get("db") or get_environ_variable(name="REDIS_DB", default=0)),
32
- "decode_responses": True,
33
- **kwargs.pop("redis_configs", {}),
34
- }
28
+ redis_configs = get_redis_configs_from_payload(payload=kwargs, keep=False)
35
29
  redis_instance = Redis(**redis_configs)
36
30
  req_queue = get_request_queue_name_from_payload(payload=kwargs, keep=False)
37
31
  res_queue = get_response_queue_name_from_payload(payload=kwargs, keep=False) or (
@@ -0,0 +1,54 @@
1
+ import uuid
2
+ from typing import Optional
3
+ from dataclasses import dataclass
4
+
5
+ from fred.settings import logger_manager
6
+
7
+ logger = logger_manager.get_logger(name=__name__)
8
+
9
+
10
+ @dataclass(frozen=True, slots=True)
11
+ class RunnerInfo:
12
+ runner_id: str
13
+ created_at: str
14
+ runner_inner_handler_classname: str
15
+ runner_inner_handler_classpath: str
16
+ lifetime: int
17
+ timeout: int
18
+
19
+ @classmethod
20
+ def create(
21
+ cls,
22
+ runner_inner_handler_classname: str,
23
+ runner_inner_handler_classpath: str,
24
+ runner_id: Optional[str] = None,
25
+ created_at: Optional[str] = None,
26
+ lifetime: int = 3600, # Default to 1 hour
27
+ timeout: int = 10, # Default to 10 seconds
28
+ ) -> "RunnerInfo":
29
+ from fred.utils.dateops import datetime_utcnow
30
+ return cls(
31
+ runner_id=runner_id or str(uuid.uuid4()),
32
+ runner_inner_handler_classname=runner_inner_handler_classname,
33
+ runner_inner_handler_classpath=runner_inner_handler_classpath,
34
+ created_at=created_at or datetime_utcnow().isoformat(),
35
+ lifetime=lifetime,
36
+ timeout=timeout,
37
+ )
38
+
39
+ def get_start_event(self, **kwargs) -> dict:
40
+ runner_id = kwargs.pop("runner_id", self.runner_id)
41
+ payload = {
42
+ "lifetime": self.lifetime,
43
+ "timeout": self.timeout,
44
+ "runner_configs": {
45
+ "id": runner_id,
46
+ "import_pattern": self.runner_inner_handler_classpath,
47
+ "handler_classname": self.runner_inner_handler_classname,
48
+ },
49
+ **kwargs,
50
+ }
51
+ return {
52
+ "input": payload,
53
+ "id": runner_id,
54
+ }
@@ -0,0 +1,26 @@
1
+ from dataclasses import dataclass
2
+
3
+ from fred.settings import logger_manager
4
+ from fred.worker.runner.info import RunnerInfo
5
+ from fred.worker.runner.handler import RunnerHandler
6
+ from fred.worker.runner.plugins.interface import PluginInterface
7
+
8
+ logger = logger_manager.get_logger(name=__name__)
9
+
10
+
11
+ @dataclass(frozen=True, slots=True)
12
+ class LocalPlugin(PluginInterface):
13
+
14
+ def _execute(
15
+ self,
16
+ runner_info: RunnerInfo,
17
+ outer_handler: RunnerHandler,
18
+ **kwargs
19
+ ):
20
+ """Execute the runner locally using the provided outer handler.
21
+ Args:
22
+ runner_info (RunnerInfo): Information about the runner to execute.
23
+ outer_handler (RunnerHandler): The outer handler to use for execution.
24
+ **kwargs: Additional keyword arguments to pass to the execution method implemented by the subclass.
25
+ """
26
+ outer_handler.run(event=runner_info.get_start_event(**kwargs))
@@ -0,0 +1,15 @@
1
+ import enum
2
+ from dataclasses import dataclass
3
+
4
+ from fred.settings import logger_manager
5
+ from fred.worker.runner.plugins._local import LocalPlugin
6
+
7
+ logger = logger_manager.get_logger(name=__name__)
8
+
9
+
10
+ class PluginCatalog(enum.Enum):
11
+ """Enum for the different plugins available in FRED."""
12
+
13
+ LOCAL = LocalPlugin.auto()
14
+ RUNPOD = None # Placeholder for future RunPod plugin
15
+ LAMBDA = None # Placeholder for future AWS Lambda plugin
@@ -0,0 +1,152 @@
1
+ from dataclasses import dataclass
2
+ from threading import Thread
3
+ from typing import Optional
4
+
5
+ from redis import Redis
6
+
7
+ from fred.settings import logger_manager
8
+ from fred.worker.runner.info import RunnerInfo
9
+ from fred.worker.runner.handler import RunnerHandler
10
+ from fred.worker.runner.utils import get_redis_configs_from_payload
11
+ from fred.utils.dateops import datetime_utcnow
12
+
13
+ logger = logger_manager.get_logger(name=__name__)
14
+
15
+
16
+ @dataclass(frozen=True, slots=True)
17
+ class PluginInterface:
18
+ """Interface for the different plugins available for FRED Runners."""
19
+ redis: Redis
20
+
21
+ @classmethod
22
+ def auto(cls, **kwargs) -> "PluginInterface":
23
+ """Auto-instantiate the plugin interface with a Redis instance.
24
+ If a Redis instance is not provided, it will create one using configurations
25
+ extracted from the provided keyword arguments.
26
+ Args:
27
+ **kwargs: Keyword arguments that may contain Redis configurations or an existing Redis instance.
28
+ Returns:
29
+ PluginInterface: An instance of the PluginInterface with a Redis connection.
30
+ """
31
+ redis = kwargs.pop("instance", None) or Redis(**get_redis_configs_from_payload(payload=kwargs, keep=False))
32
+ return cls(redis=redis)
33
+
34
+ def _execute(
35
+ self,
36
+ runner_info: RunnerInfo,
37
+ outer_handler: RunnerHandler,
38
+ **kwargs
39
+ ):
40
+ raise NotImplementedError("This method should be overridden by subclasses.")
41
+
42
+ def _monitor(self, runner_info: RunnerInfo, **kwargs):
43
+ raise NotImplementedError("This method should be overridden by subclasses.")
44
+
45
+ def monitor(
46
+ self,
47
+ runner_info: RunnerInfo,
48
+ blocking: bool = False,
49
+ timeout: Optional[int] = None,
50
+ **kwargs
51
+ ) -> Optional[Thread]:
52
+ """Start monitoring the runner in a separate thread.
53
+ Args:
54
+ runner_info (RunnerInfo): Information about the runner to monitor.
55
+ blocking (bool, optional): Whether to block the main thread until monitoring is complete. Defaults to False.
56
+ timeout (Optional[int], optional): Timeout in seconds for the monitoring thread. Defaults to None.
57
+ **kwargs: Additional keyword arguments to pass to the monitoring method.
58
+ Returns:
59
+ Optional[Thread]: The thread object for the monitoring thread if not blocking, else None."""
60
+ # Start monitoring in a separate thread
61
+ thread = Thread(
62
+ target=self._monitor,
63
+ kwargs={
64
+ "runner_info": runner_info,
65
+ "blocking": blocking,
66
+ **kwargs
67
+ },
68
+ daemon=True,
69
+ )
70
+ thread.start()
71
+ # If blocking is True, wait for the thread to finish or timeout
72
+ return thread.join(timeout=timeout) if blocking else thread
73
+
74
+ def _execute_wrapper(
75
+ self,
76
+ runner_info: RunnerInfo,
77
+ outer_handler: RunnerHandler,
78
+ **kwargs
79
+ ) -> str:
80
+ """Wrapper method to handle execution and include error logging.
81
+
82
+ Since we don't control the implementation of the _execute method in subclasses, we
83
+ need to wrap it to add error handling and logging.
84
+
85
+ Args:
86
+ runner_info (RunnerInfo): Information about the runner to execute.
87
+ outer_handler (RunnerHandler): The outer handler to use for execution.
88
+ **kwargs: Additional keyword arguments to pass to the execution method implemented by the subclass.
89
+ """
90
+ runner_id = runner_info.runner_id
91
+ self.redis.set(f"runner:{runner_id}:status", f"STARTING:{datetime_utcnow().isoformat()}")
92
+ try:
93
+ self._execute(
94
+ runner_info=runner_info,
95
+ outer_handler=outer_handler,
96
+ **kwargs
97
+ )
98
+ except Exception as e:
99
+ self.redis.set(f"runner:{runner_id}:status", f"ERROR:{datetime_utcnow().isoformat()}")
100
+ logger.error(f"Error executing runner '{runner_id}': {e}")
101
+ raise
102
+ return runner_id
103
+
104
+ def execute(
105
+ self,
106
+ runner_info: RunnerInfo,
107
+ outer_handler: RunnerHandler,
108
+ wait_for_exec: bool = False,
109
+ timeout: Optional[int] = None,
110
+ enable_monitor: bool = False,
111
+ wait_for_monitor: bool = False,
112
+ **kwargs
113
+ ) -> Thread:
114
+ """Execute the runner using the specified plugin.
115
+ This method starts the execution of the runner in a separate thread. It can also
116
+ optionally start a monitoring thread to monitor the runner's status.
117
+ Args:
118
+ runner_info (RunnerInfo): Information about the runner to execute.
119
+ outer_handler (RunnerHandler): The outer handler to use for execution.
120
+ wait_for_exec (bool, optional): Whether to wait for the execution thread to complete. Defaults to False.
121
+ timeout (Optional[int], optional): Timeout in seconds for the execution thread. Defaults to None.
122
+ enable_monitor (bool, optional): Whether to enable monitoring of the runner. Defaults to False.
123
+ wait_for_monitor (bool, optional): Whether to wait for the monitoring thread to complete. Defaults to False.
124
+ **kwargs: Additional keyword arguments to pass to the execution and monitoring methods.
125
+ Returns:
126
+ Thread: The thread object for the execution.
127
+ """
128
+ runner_id = runner_info.runner_id
129
+ logger.info(f"Starting thread runner '{runner_id}' using plugin '{self.__class__.__name__}'.")
130
+ thread = Thread(
131
+ target=self._execute_wrapper,
132
+ kwargs={
133
+ "runner_info": runner_info,
134
+ "outer_handler": outer_handler,
135
+ **kwargs
136
+ },
137
+ daemon=True,
138
+ )
139
+ thread.start()
140
+ if enable_monitor:
141
+ self.monitor(
142
+ runner_info=runner_info,
143
+ blocking=wait_for_monitor,
144
+ timeout=timeout,
145
+ **kwargs
146
+ )
147
+ else:
148
+ logger.info(f"Monitoring disabled for runner '{runner_id}'.")
149
+ if wait_for_exec:
150
+ logger.info(f"Waiting for execution of runner '{runner_id}' to complete.")
151
+ thread.join()
152
+ return thread
@@ -47,3 +47,28 @@ def get_response_queue_name_from_payload(
47
47
  default=None,
48
48
  keep=keep,
49
49
  )
50
+
51
+ def get_redis_configs_from_payload(
52
+ payload: dict,
53
+ keep: bool = False,
54
+ ) -> dict:
55
+ for host_key in ["host", "redis_host"]:
56
+ if (host := payload.get(host_key) if keep else payload.pop(host_key, None)):
57
+ break
58
+ for port_key in ["port", "redis_port"]:
59
+ if (port := payload.get(port_key) if keep else payload.pop(port_key, None)):
60
+ break
61
+ for password_key in ["password", "redis_password"]:
62
+ if (password := payload.get(password_key) if keep else payload.pop(password_key, None)):
63
+ break
64
+ for db_key in ["db", "redis_db"]:
65
+ if (db := payload.get(db_key) if keep else payload.pop(db_key, None)):
66
+ break
67
+ return {
68
+ "host": host or get_environ_variable(name="REDIS_HOST", default="localhost"),
69
+ "port": int(port or get_environ_variable(name="REDIS_PORT", default=6379)),
70
+ "password": password or get_environ_variable(name="REDIS_PASSWORD", default=None),
71
+ "db": int(db or get_environ_variable(name="REDIS_DB", default=0)),
72
+ "decode_responses": True,
73
+ **(payload.get("redis_configs", {}) if keep else payload.pop("redis_configs", {})),
74
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fred-oss
3
- Version: 0.11.0
3
+ Version: 0.13.0
4
4
  Summary: FREDOSS
5
5
  Home-page: https://fred.fahera.mx
6
6
  Author: Fahera Research, Education, and Development
@@ -30,7 +30,12 @@ src/main/fred/worker/interface.py
30
30
  src/main/fred/worker/runner/__init__.py
31
31
  src/main/fred/worker/runner/client.py
32
32
  src/main/fred/worker/runner/handler.py
33
+ src/main/fred/worker/runner/info.py
33
34
  src/main/fred/worker/runner/utils.py
35
+ src/main/fred/worker/runner/plugins/__init__.py
36
+ src/main/fred/worker/runner/plugins/_local.py
37
+ src/main/fred/worker/runner/plugins/catalog.py
38
+ src/main/fred/worker/runner/plugins/interface.py
34
39
  src/main/fred_oss.egg-info/PKG-INFO
35
40
  src/main/fred_oss.egg-info/SOURCES.txt
36
41
  src/main/fred_oss.egg-info/dependency_links.txt
@@ -1 +0,0 @@
1
- 0.11.0
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes