argparse UPath typed path args becomes pathlib.Path instead of upath.UPath
I am using Universal Pathlib (UPath) as unified pathlib-compatible interface for local and remote filesystems (e.g. S3). When trying to use it with argparser cli instead of getting a UPath the arg paths were Path type.
Delving into the issue, it seems to be a result of UPath being a subclass of Path and typed settings code assuming it should be Path.
Potential fix
This is how I am currently handling this problem in our code:
def handle_path(type_: type[Path], default: Default, is_optional: bool) -> StrDict:
"""Patched ts.cli_argparse.handle_path to fix handling UPath type."""
kwargs = {"type": type_, "metavar": "PATH"}
if isinstance(default, (type_, str)):
kwargs["default"] = str(default)
elif is_optional:
kwargs["default"] = None
return kwargs
def to_path(value: Path | str, cls: type) -> Path:
"""Patched ts.convertors.to_path to use cls arg"""
return cls(value)
def to_resolved_path(value: Path | str, cls: type) -> Path:
"""Patched ts.convertors.to_path to use cls arg"""
return cls(value).resolve()
def apply_upath_fixes() -> None:
"""Patch typed settings Path type functions to support UPath."""
# Patch DEFAULT_TYPES since UPath is a subclass of Path and incorrectly cast as Path
ts.cli_argparse.DEFAULT_TYPES[Path] = handle_path
# Replace converters with UPath type aware versions
ts.converters.to_path = to_path
ts.converters.to_resolved_path = to_resolved_path
Would you be open to a PR to fix this?