directory path types with argparse

前端 未结 3 1210
盖世英雄少女心
盖世英雄少女心 2020-12-13 08:35

My python script needs to read files from a directory passed on the command line. I have defined a readable_dir type as below to be used with argparse for validating that th

3条回答
  •  半阙折子戏
    2020-12-13 08:57

    I submitted a patch for "path arguments" to the Python standard library mailing list a few months ago.

    With this PathType class, you can simply specify the following argument type to match only an existing directory--anything else will give an error message:

    type = PathType(exists=True, type='dir')
    

    Here's the code, which could be easily modified to require specific file/directory permissions as well:

    from argparse import ArgumentTypeError as err
    import os
    
    class PathType(object):
        def __init__(self, exists=True, type='file', dash_ok=True):
            '''exists:
                    True: a path that does exist
                    False: a path that does not exist, in a valid parent directory
                    None: don't care
               type: file, dir, symlink, None, or a function returning True for valid paths
                    None: don't care
               dash_ok: whether to allow "-" as stdin/stdout'''
    
            assert exists in (True, False, None)
            assert type in ('file','dir','symlink',None) or hasattr(type,'__call__')
    
            self._exists = exists
            self._type = type
            self._dash_ok = dash_ok
    
        def __call__(self, string):
            if string=='-':
                # the special argument "-" means sys.std{in,out}
                if self._type == 'dir':
                    raise err('standard input/output (-) not allowed as directory path')
                elif self._type == 'symlink':
                    raise err('standard input/output (-) not allowed as symlink path')
                elif not self._dash_ok:
                    raise err('standard input/output (-) not allowed')
            else:
                e = os.path.exists(string)
                if self._exists==True:
                    if not e:
                        raise err("path does not exist: '%s'" % string)
    
                    if self._type is None:
                        pass
                    elif self._type=='file':
                        if not os.path.isfile(string):
                            raise err("path is not a file: '%s'" % string)
                    elif self._type=='symlink':
                        if not os.path.symlink(string):
                            raise err("path is not a symlink: '%s'" % string)
                    elif self._type=='dir':
                        if not os.path.isdir(string):
                            raise err("path is not a directory: '%s'" % string)
                    elif not self._type(string):
                        raise err("path not valid: '%s'" % string)
                else:
                    if self._exists==False and e:
                        raise err("path exists: '%s'" % string)
    
                    p = os.path.dirname(os.path.normpath(string)) or '.'
                    if not os.path.isdir(p):
                        raise err("parent path is not a directory: '%s'" % p)
                    elif not os.path.exists(p):
                        raise err("parent directory does not exist: '%s'" % p)
    
            return string
    

提交回复
热议问题