Hi, Similarly to argparse.FileType, people find themselves writing the same checks over and over when getting directories from the CLI (and more generally, paths) and it seems this could be simplified directly in argparse. I suggest leveraging pathlib to add a new Path argument type. I wrote a draft patch, any comments on the API are welcome: ---- class PathType(object): """Factory for creating pathlib.Path object types Instances of PathType are typically passed as type= arguments to the ArgumentParser add_argument() method. Keyword Arguments: - exists -- A boolean set to True if the path should point to something that exists, False if it should point to something that does not exist, or None to not check anything. - parents_exists -- If set to True, raise an error if the path should be in a directory that exists - check_type -- A callback taking a Path and returning a boolean which check the type of the path before returning it. Typically used with Path.is_{file,dir,...} """ def __init__(self, exists=None, parents_exist=None, check_type=None): self._exists = exists self._parents_exist = parents_exist self._check_type = check_type def __call__(self, string): import pathlib path = pathlib.Path(string) if self._exists is True and not path.exists(): raise ArgumentTypeError(_("'{}' doesn't exist".format(string))) if self._exists is False and path.exists(): raise ArgumentTypeError(_("'{}' already exists".format(string))) if self._check_type is not None and not self._check_type(path): raise ArgumentTypeError(_("'{}' is not the correct type of path".format(string))) return path ---- A few comments: * To avoid option clutter, I only included *checks* on the path, as opposed to things to *do* on the path, e.g mkdir=True or mkdir_parents=True options. I'm not especially against their inclusion if you think that would also be useful. * I also did not include os.access() checks because I wasn't sure of the API to use. is_readable=True/is_writeable=True? I can add that if needed. * The check_type API is not very friendly, you basically have to pass stuff like check_type=Path.is_file. Another option would be to have a type='file' / type='dir' / ... option but it's less flexible. Any suggestions? Here's some other instances where people have tried to do that: https://stackoverflow.com/questions/11415570/directory-path-types-with-argpa... https://mail.python.org/pipermail/stdlib-sig/2015-July/000990.html There's also precedent in third party libraries: https://click.palletsprojects.com/en/7.x/api/#click.Path Note that it's also easy to define a DirType analog to FileType with a simpler API: class DirType(PathType): def __init__(self, exists=None, parents_exist=None): import pathlib super().__init__(self, exists=exists, parents_exist=parents_exist, check_type=pathlib.Path.is_dir) and if we want that one to return a bare path: def __call__(self, string): return str(super().__call__(string)) Any comments or suggestions? :-) -- Antoine Pietri
participants (1)
-
Antoine Pietri