griptape-nodes 0.61.0__py3-none-any.whl → 0.62.1__py3-none-any.whl
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.
- griptape_nodes/common/macro_parser/core.py +4 -4
- griptape_nodes/common/macro_parser/exceptions.py +3 -3
- griptape_nodes/common/macro_parser/resolution.py +2 -2
- griptape_nodes/common/project_templates/default_project_template.py +5 -10
- griptape_nodes/common/project_templates/directory.py +5 -5
- griptape_nodes/common/project_templates/loader.py +8 -7
- griptape_nodes/common/project_templates/project.py +1 -1
- griptape_nodes/common/project_templates/situation.py +5 -17
- griptape_nodes/common/project_templates/validation.py +3 -3
- griptape_nodes/drivers/storage/griptape_cloud_storage_driver.py +2 -2
- griptape_nodes/drivers/storage/local_storage_driver.py +2 -2
- griptape_nodes/node_library/workflow_registry.py +1 -1
- griptape_nodes/retained_mode/events/project_events.py +208 -93
- griptape_nodes/retained_mode/managers/event_manager.py +24 -9
- griptape_nodes/retained_mode/managers/library_manager.py +12 -21
- griptape_nodes/retained_mode/managers/os_manager.py +54 -6
- griptape_nodes/retained_mode/managers/project_manager.py +709 -259
- griptape_nodes/retained_mode/managers/static_files_manager.py +1 -5
- griptape_nodes/retained_mode/managers/sync_manager.py +4 -1
- griptape_nodes/retained_mode/managers/workflow_manager.py +2 -10
- griptape_nodes/traits/button.py +2 -1
- {griptape_nodes-0.61.0.dist-info → griptape_nodes-0.62.1.dist-info}/METADATA +1 -1
- {griptape_nodes-0.61.0.dist-info → griptape_nodes-0.62.1.dist-info}/RECORD +25 -26
- {griptape_nodes-0.61.0.dist-info → griptape_nodes-0.62.1.dist-info}/WHEEL +1 -1
- griptape_nodes/common/project_templates/defaults/project_template.yml +0 -89
- {griptape_nodes-0.61.0.dist-info → griptape_nodes-0.62.1.dist-info}/entry_points.txt +0 -0
|
@@ -155,7 +155,49 @@ class OSManager:
|
|
|
155
155
|
"""
|
|
156
156
|
# Expand environment variables first, then tilde
|
|
157
157
|
expanded_vars = os.path.expandvars(path_str)
|
|
158
|
-
return Path(expanded_vars).expanduser()
|
|
158
|
+
return self.resolve_path_safely(Path(expanded_vars).expanduser())
|
|
159
|
+
|
|
160
|
+
def resolve_path_safely(self, path: Path) -> Path:
|
|
161
|
+
"""Resolve a path consistently across platforms.
|
|
162
|
+
|
|
163
|
+
Unlike Path.resolve() which behaves differently on Windows vs Unix
|
|
164
|
+
for non-existent paths, this method provides consistent behavior:
|
|
165
|
+
- Converts relative paths to absolute (using CWD as base)
|
|
166
|
+
- Normalizes path separators and removes . and ..
|
|
167
|
+
- Does NOT resolve symlinks if path doesn't exist
|
|
168
|
+
- Does NOT change path based on CWD for absolute paths
|
|
169
|
+
|
|
170
|
+
Use this instead of .resolve() when:
|
|
171
|
+
- Path might not exist (file creation, validation, user input)
|
|
172
|
+
- You need consistent cross-platform comparison
|
|
173
|
+
- You're about to create the file/directory
|
|
174
|
+
|
|
175
|
+
Use .resolve() when:
|
|
176
|
+
- Path definitely exists and you need symlink resolution
|
|
177
|
+
- You're checking actual file locations
|
|
178
|
+
|
|
179
|
+
Args:
|
|
180
|
+
path: Path to resolve (relative or absolute, existing or not)
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
Absolute, normalized Path object
|
|
184
|
+
|
|
185
|
+
Examples:
|
|
186
|
+
# Relative path
|
|
187
|
+
resolve_path_safely(Path("relative/file.txt"))
|
|
188
|
+
→ Path("/current/dir/relative/file.txt")
|
|
189
|
+
|
|
190
|
+
# Absolute non-existent path (Windows safe)
|
|
191
|
+
resolve_path_safely(Path("/abs/nonexistent/path"))
|
|
192
|
+
→ Path("/abs/nonexistent/path") # NOT resolved relative to CWD
|
|
193
|
+
"""
|
|
194
|
+
# Convert to absolute if relative
|
|
195
|
+
if not path.is_absolute():
|
|
196
|
+
path = Path.cwd() / path
|
|
197
|
+
|
|
198
|
+
# Normalize (remove . and .., collapse slashes) without resolving symlinks
|
|
199
|
+
# This works consistently even for non-existent paths on Windows
|
|
200
|
+
return Path(os.path.normpath(path))
|
|
159
201
|
|
|
160
202
|
def _resolve_file_path(self, path_str: str, *, workspace_only: bool = False) -> Path:
|
|
161
203
|
"""Resolve a file path, handling absolute, relative, and tilde paths.
|
|
@@ -172,7 +214,7 @@ class OSManager:
|
|
|
172
214
|
# Expand tilde and environment variables for absolute paths or paths starting with ~
|
|
173
215
|
return self._expand_path(path_str)
|
|
174
216
|
# Both workspace and system-wide modes resolve relative to current directory
|
|
175
|
-
return (self._get_workspace_path() / path_str)
|
|
217
|
+
return self.resolve_path_safely(self._get_workspace_path() / path_str)
|
|
176
218
|
except (ValueError, RuntimeError):
|
|
177
219
|
if workspace_only:
|
|
178
220
|
msg = f"Path '{path_str}' not found, using workspace directory: {self._get_workspace_path()}"
|
|
@@ -193,8 +235,11 @@ class OSManager:
|
|
|
193
235
|
workspace = GriptapeNodes.ConfigManager().workspace_path
|
|
194
236
|
|
|
195
237
|
# Ensure both paths are resolved for comparison
|
|
238
|
+
# Both path and workspace should use .resolve() to follow symlinks consistently
|
|
239
|
+
# (e.g., /var -> /private/var on macOS). Even if path doesn't exist yet,
|
|
240
|
+
# .resolve() will resolve parent directories and symlinks in the path.
|
|
196
241
|
path = path.resolve()
|
|
197
|
-
workspace = workspace.resolve()
|
|
242
|
+
workspace = workspace.resolve() # Workspace should always exist
|
|
198
243
|
|
|
199
244
|
msg = f"Validating path: {path} against workspace: {workspace}"
|
|
200
245
|
logger.debug(msg)
|
|
@@ -217,6 +262,9 @@ class OSManager:
|
|
|
217
262
|
need the \\?\ prefix to work correctly. This method transparently adds
|
|
218
263
|
the prefix when needed on Windows.
|
|
219
264
|
|
|
265
|
+
Note: This method assumes the path exists or will exist. For non-existent
|
|
266
|
+
paths that need cross-platform normalization, use resolve_path_safely() first.
|
|
267
|
+
|
|
220
268
|
Args:
|
|
221
269
|
path: Path object to convert to string
|
|
222
270
|
|
|
@@ -443,7 +491,7 @@ class OSManager:
|
|
|
443
491
|
directory = self._expand_path(request.directory_path)
|
|
444
492
|
else:
|
|
445
493
|
# Both workspace and system-wide modes resolve relative to current directory
|
|
446
|
-
directory = (self._get_workspace_path() / request.directory_path)
|
|
494
|
+
directory = self.resolve_path_safely(self._get_workspace_path() / request.directory_path)
|
|
447
495
|
|
|
448
496
|
# Check if directory exists
|
|
449
497
|
if not directory.exists():
|
|
@@ -1056,9 +1104,9 @@ class OSManager:
|
|
|
1056
1104
|
|
|
1057
1105
|
# Resolve path - if absolute, use as-is; if relative, align to workspace
|
|
1058
1106
|
if is_absolute:
|
|
1059
|
-
file_path = Path(full_path_str)
|
|
1107
|
+
file_path = self.resolve_path_safely(Path(full_path_str))
|
|
1060
1108
|
else:
|
|
1061
|
-
file_path = (self._get_workspace_path() / full_path_str)
|
|
1109
|
+
file_path = self.resolve_path_safely(self._get_workspace_path() / full_path_str)
|
|
1062
1110
|
|
|
1063
1111
|
# Check if it already exists - warn but treat as success
|
|
1064
1112
|
if file_path.exists():
|