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-argparse
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
_______________________________________________
Python-ideas mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/DWNA6IMMLVJZ4HXZOABW45SLN35FWCXB/
Code of Conduct: http://python.org/psf/codeofconduct/