madsci.node_module 0.4.3__tar.gz → 0.4.4__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: madsci.node_module
3
- Version: 0.4.3
3
+ Version: 0.4.4
4
4
  Summary: The Modular Autonomous Discovery for Science (MADSci) Node Module Helper Classes.
5
5
  Author-Email: Tobias Ginsburg <tginsburg@anl.gov>, "Ryan D. Lewis" <ryan.lewis@anl.gov>, Casey Stone <cstone@anl.gov>, Doga Ozgulbas <dozgulbas@anl.gov>
6
6
  License: MIT
@@ -26,7 +26,7 @@ from madsci.client.resource_client import ResourceClient
26
26
  from madsci.common.exceptions import (
27
27
  ActionNotImplementedError,
28
28
  )
29
- from madsci.common.ownership import ownership_context
29
+ from madsci.common.ownership import global_ownership_info
30
30
  from madsci.common.types.action_types import (
31
31
  ActionDefinition,
32
32
  ActionRequest,
@@ -58,6 +58,7 @@ from madsci.common.utils import (
58
58
  pretty_type_repr,
59
59
  repeat_on_interval,
60
60
  threaded_daemon,
61
+ to_snake_case,
61
62
  )
62
63
  from pydantic import ValidationError
63
64
  from semver import Version
@@ -118,49 +119,48 @@ class AbstractNode:
118
119
  self.logger.log_warning(
119
120
  f"Node definition file '{node_definition_path}' not found, using default node definition."
120
121
  )
122
+ module_name = to_snake_case(self.__class__.__name__)
123
+ node_name = str(Path(node_definition_path).stem)
121
124
  self.node_definition = NodeDefinition(
122
- module_name=self.__class__.__name__,
123
- node_name=self.__class__.__name__,
124
- module_version=self.module_version,
125
+ node_name=node_name, module_name=module_name
125
126
  )
126
127
  else:
127
128
  self.node_definition = NodeDefinition.from_yaml(node_definition_path)
129
+ global_ownership_info.node_id = self.node_definition.node_id
130
+ self._configure_clients()
128
131
 
129
- with ownership_context(node_id=self.node_definition.node_id):
130
- self._configure_clients()
131
-
132
- # * Check Node Version
133
- if (
134
- Version.parse(self.module_version).compare(
135
- self.node_definition.module_version
136
- )
137
- < 0
138
- ):
139
- self.logger.log_warning(
140
- "The module version in the Node Module's source code does not match the version specified in your Node Definition. Your module may have been updated. We recommend checking to ensure compatibility, and then updating the version in your node definition to match."
141
- )
142
-
143
- # * Synthesize the node info
144
- self.node_info = NodeInfo.from_node_def_and_config(
145
- self.node_definition, self.config
132
+ # * Check Node Version
133
+ if (
134
+ Version.parse(self.module_version).compare(
135
+ self.node_definition.module_version
136
+ )
137
+ < 0
138
+ ):
139
+ self.logger.log_warning(
140
+ "The module version in the Node Module's source code does not match the version specified in your Node Definition. Your module may have been updated. We recommend checking to ensure compatibility, and then updating the version in your node definition to match."
146
141
  )
147
142
 
148
- # * Combine the node definition and classes's capabilities
149
- self._populate_capabilities()
150
-
151
- # * Add the action decorators to the node (and node info)
152
- for action_callable in self.__class__.__dict__.values():
153
- if hasattr(action_callable, "__is_madsci_action__"):
154
- self._add_action(
155
- func=action_callable,
156
- action_name=action_callable.__madsci_action_name__,
157
- description=action_callable.__madsci_action_description__,
158
- blocking=action_callable.__madsci_action_blocking__,
159
- )
143
+ # * Synthesize the node info
144
+ self.node_info = NodeInfo.from_node_def_and_config(
145
+ self.node_definition, self.config
146
+ )
147
+
148
+ # * Combine the node definition and classes's capabilities
149
+ self._populate_capabilities()
150
+
151
+ # * Add the action decorators to the node (and node info)
152
+ for action_callable in self.__class__.__dict__.values():
153
+ if hasattr(action_callable, "__is_madsci_action__"):
154
+ self._add_action(
155
+ func=action_callable,
156
+ action_name=action_callable.__madsci_action_name__,
157
+ description=action_callable.__madsci_action_description__,
158
+ blocking=action_callable.__madsci_action_blocking__,
159
+ )
160
160
 
161
- # * Save the node info and update definition, if possible
162
- if self.config.update_node_files:
163
- self._update_node_info_and_definition()
161
+ # * Save the node info and update definition, if possible
162
+ if self.config.update_node_files:
163
+ self._update_node_info_and_definition()
164
164
 
165
165
  """------------------------------------------------------------------------------------------------"""
166
166
  """Node Lifecycle and Public Methods"""
@@ -169,17 +169,17 @@ class AbstractNode:
169
169
  def start_node(self) -> None:
170
170
  """Called once to start the node."""
171
171
 
172
- with ownership_context(node_id=self.node_definition.node_id):
173
- # * Update EventClient with logging parameters
174
- self._configure_clients()
172
+ global_ownership_info.node_id = self.node_definition.node_id
173
+ # * Update EventClient with logging parameters
174
+ self._configure_clients()
175
175
 
176
- # * Log startup info
177
- self.logger.log_debug(f"{self.node_definition=}")
176
+ # * Log startup info
177
+ self.logger.log_debug(f"{self.node_definition=}")
178
178
 
179
- # * Kick off the startup logic in a separate thread
180
- # * This allows implementations to start servers, listeners, etc.
181
- # * in parrallel
182
- self._startup()
179
+ # * Kick off the startup logic in a separate thread
180
+ # * This allows implementations to start servers, listeners, etc.
181
+ # * in parrallel
182
+ self._startup()
183
183
 
184
184
  def status_handler(self) -> None:
185
185
  """Called periodically to update the node status. Should set `self.node_status`"""
@@ -15,7 +15,7 @@ from fastapi.background import BackgroundTasks
15
15
  from fastapi.datastructures import UploadFile
16
16
  from fastapi.routing import APIRouter
17
17
  from madsci.client.node.rest_node_client import RestNodeClient
18
- from madsci.common.ownership import ownership_context
18
+ from madsci.common.ownership import global_ownership_info
19
19
  from madsci.common.types.action_types import (
20
20
  ActionRequest,
21
21
  ActionResult,
@@ -64,33 +64,33 @@ class RestNode(AbstractNode):
64
64
 
65
65
  def start_node(self, testing: bool = False) -> None:
66
66
  """Start the node."""
67
- with ownership_context(node_id=self.node_definition.node_id):
68
- url = AnyUrl(getattr(self.config, "node_url", "http://127.0.0.1:2000"))
69
- if not testing:
70
- self.logger.log_debug("Running node in production mode")
71
- import uvicorn
72
-
73
- self.rest_api = FastAPI(lifespan=self._lifespan)
74
-
75
- # Middleware to set ownership context for each request
76
- @self.rest_api.middleware("http")
77
- async def ownership_middleware(
78
- request: Request, call_next: Callable
79
- ) -> Response:
80
- with ownership_context(node_id=self.node_definition.node_id):
81
- return await call_next(request)
82
-
83
- self._configure_routes()
84
- uvicorn.run(
85
- self.rest_api,
86
- host=url.host if url.host else "127.0.0.1",
87
- port=url.port if url.port else 2000,
88
- **getattr(self.config, "uvicorn_kwargs", {}),
89
- )
90
- else:
91
- self.logger.log_debug("Running node in test mode")
92
- self.rest_api = FastAPI(lifespan=self._lifespan)
93
- self._configure_routes()
67
+ global_ownership_info.node_id = self.node_definition.node_id
68
+ url = AnyUrl(getattr(self.config, "node_url", "http://127.0.0.1:2000"))
69
+ if not testing:
70
+ self.logger.log_debug("Running node in production mode")
71
+ import uvicorn # noqa: PLC0415
72
+
73
+ self.rest_api = FastAPI(lifespan=self._lifespan)
74
+
75
+ # Middleware to set ownership context for each request
76
+ @self.rest_api.middleware("http")
77
+ async def ownership_middleware(
78
+ request: Request, call_next: Callable
79
+ ) -> Response:
80
+ global_ownership_info.node_id = self.node_definition.node_id
81
+ return await call_next(request)
82
+
83
+ self._configure_routes()
84
+ uvicorn.run(
85
+ self.rest_api,
86
+ host=url.host if url.host else "127.0.0.1",
87
+ port=url.port if url.port else 2000,
88
+ **getattr(self.config, "uvicorn_kwargs", {}),
89
+ )
90
+ else:
91
+ self.logger.log_debug("Running node in test mode")
92
+ self.rest_api = FastAPI(lifespan=self._lifespan)
93
+ self._configure_routes()
94
94
 
95
95
  """------------------------------------------------------------------------------------------------"""
96
96
  """Interface Methods"""
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "madsci.node_module"
3
- version = "0.4.3"
3
+ version = "0.4.4"
4
4
  description = "The Modular Autonomous Discovery for Science (MADSci) Node Module Helper Classes."
5
5
  authors = [
6
6
  { name = "Tobias Ginsburg", email = "tginsburg@anl.gov" },