-
-
Notifications
You must be signed in to change notification settings - Fork 863
Normalize incoming Home RPC path arguments to the remote host OS #5409
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -13,5 +13,58 @@ | |||||||||||||||||||||
| # limitations under the License. | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| import inspect | ||||||||||||||||||||||
| import os | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| class BaseRPCHandler: | ||||||||||||||||||||||
| PATH_ARGUMENT_MARKERS = ( | ||||||||||||||||||||||
| "path", | ||||||||||||||||||||||
| "paths", | ||||||||||||||||||||||
| "dir", | ||||||||||||||||||||||
| "dirs", | ||||||||||||||||||||||
| "directory", | ||||||||||||||||||||||
| "directories", | ||||||||||||||||||||||
| "file", | ||||||||||||||||||||||
| "files", | ||||||||||||||||||||||
| "folder", | ||||||||||||||||||||||
| "folders", | ||||||||||||||||||||||
| ) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| factory = None | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def __getattribute__(self, name): | ||||||||||||||||||||||
| attr = super().__getattribute__(name) | ||||||||||||||||||||||
| if name.startswith("_") or not callable(attr): | ||||||||||||||||||||||
| return attr | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def wrapped(*args, **kwargs): | ||||||||||||||||||||||
| args, kwargs = self._normalize_path_arguments(attr, args, kwargs) | ||||||||||||||||||||||
| return attr(*args, **kwargs) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| return wrapped | ||||||||||||||||||||||
|
Comment on lines
+41
to
+45
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def _normalize_path_arguments(self, method, args, kwargs): | ||||||||||||||||||||||
| bound_args = inspect.signature(method).bind_partial(*args, **kwargs) | ||||||||||||||||||||||
| for param_name, value in bound_args.arguments.items(): | ||||||||||||||||||||||
| if not self._is_path_argument(param_name): | ||||||||||||||||||||||
| continue | ||||||||||||||||||||||
| bound_args.arguments[param_name] = self._normalize_path_value(value) | ||||||||||||||||||||||
| return bound_args.args, bound_args.kwargs | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def _is_path_argument(self, param_name): | ||||||||||||||||||||||
| parts = param_name.lower().split("_") | ||||||||||||||||||||||
| return any(marker in parts for marker in self.PATH_ARGUMENT_MARKERS) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def _normalize_path_value(self, value): | ||||||||||||||||||||||
| if not value: | ||||||||||||||||||||||
| return value | ||||||||||||||||||||||
| if isinstance(value, str): | ||||||||||||||||||||||
|
||||||||||||||||||||||
| if isinstance(value, str): | |
| if isinstance(value, str): | |
| sep = os.sep | |
| altsep = os.path.altsep | |
| # Normalize alternative separators to the host OS separator before normpath. | |
| if altsep: | |
| value = value.replace(altsep, sep) | |
| else: | |
| # On POSIX, treat backslashes from Windows-style paths as separators. | |
| value = value.replace("\\", sep) |
Copilot
AI
Mar 26, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_normalize_path_value handles strings and some iterables, but dicts are left unchanged and fall through to return value. RPC params often contain nested objects (e.g., project configuration dicts with a location path), so those nested paths won’t be normalized. Consider adding dict recursion (normalize values for keys matching the path markers / known path keys like location).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
__getattribute__wraps any callable attribute, which includesfactory(the JSONRPC server factory instance is callable because it implements__call__). This will causeself.factoryto return the wrapper function instead of the factory object, breaking usages likeself.factory.notify_clients(...)andself.factory.manager...across RPC handlers. Fix by only wrapping callables that are methods defined on the handler class (e.g., useinspect.getattr_static(type(self), name)to detectfunction/staticmethod/classmethoddescriptors) and leave instance attributes likefactoryuntouched.