madsci.node_module 0.4.2__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.2
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,45 +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
  )
121
- self.node_definition = NodeDefinition()
122
+ module_name = to_snake_case(self.__class__.__name__)
123
+ node_name = str(Path(node_definition_path).stem)
124
+ self.node_definition = NodeDefinition(
125
+ node_name=node_name, module_name=module_name
126
+ )
122
127
  else:
123
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()
124
131
 
125
- with ownership_context(node_id=self.node_definition.node_id):
126
- self._configure_clients()
127
-
128
- # * Check Node Version
129
- if (
130
- Version.parse(self.module_version).compare(
131
- self.node_definition.module_version
132
- )
133
- < 0
134
- ):
135
- self.logger.log_warning(
136
- "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."
137
- )
138
-
139
- # * Synthesize the node info
140
- self.node_info = NodeInfo.from_node_def_and_config(
141
- 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."
142
141
  )
143
142
 
144
- # * Combine the node definition and classes's capabilities
145
- self._populate_capabilities()
146
-
147
- # * Add the action decorators to the node (and node info)
148
- for action_callable in self.__class__.__dict__.values():
149
- if hasattr(action_callable, "__is_madsci_action__"):
150
- self._add_action(
151
- func=action_callable,
152
- action_name=action_callable.__madsci_action_name__,
153
- description=action_callable.__madsci_action_description__,
154
- blocking=action_callable.__madsci_action_blocking__,
155
- )
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
+ )
156
160
 
157
- # * Save the node info and update definition, if possible
158
- if self.config.update_node_files:
159
- 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()
160
164
 
161
165
  """------------------------------------------------------------------------------------------------"""
162
166
  """Node Lifecycle and Public Methods"""
@@ -165,17 +169,17 @@ class AbstractNode:
165
169
  def start_node(self) -> None:
166
170
  """Called once to start the node."""
167
171
 
168
- with ownership_context(node_id=self.node_definition.node_id):
169
- # * Update EventClient with logging parameters
170
- self._configure_clients()
172
+ global_ownership_info.node_id = self.node_definition.node_id
173
+ # * Update EventClient with logging parameters
174
+ self._configure_clients()
171
175
 
172
- # * Log startup info
173
- self.logger.log_debug(f"{self.node_definition=}")
176
+ # * Log startup info
177
+ self.logger.log_debug(f"{self.node_definition=}")
174
178
 
175
- # * Kick off the startup logic in a separate thread
176
- # * This allows implementations to start servers, listeners, etc.
177
- # * in parrallel
178
- 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()
179
183
 
180
184
  def status_handler(self) -> None:
181
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.2"
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" },