Source code for clize.converters

# clize -- A command-line argument parser for Python
# Copyright (C) 2011-2022 by Yann Kaiser and contributors. See AUTHORS and
# COPYING for details.
import contextlib
import sys
import io
import os
import warnings
from functools import partial

from sigtools.modifiers import autokwoargs

from clize import parser, errors, util


[docs]@parser.value_converter(name='TIME') def datetime(arg): """Parses a date into a `datetime` value Requires ``dateutil`` to be installed. """ from dateutil import parser as dparser return dparser.parse(arg)
class _FileOpener(object): def __init__(self, arg, kwargs, stdio, keep_stdio_open): self.arg = arg self.kwargs = kwargs self.stdio = stdio self.keep_stdio_open = keep_stdio_open self.validate_permissions() def validate_permissions(self): mode = self.kwargs.get('mode', 'r') if self.arg == self.stdio: return exists = os.access(self.arg, os.F_OK) if not exists: if 'r' in mode and '+' not in mode: raise errors.CliValueError( 'File does not exist: {0!r}'.format(self.arg)) else: dirname = os.path.dirname(self.arg) if not dirname or os.access(dirname, os.W_OK): return if not os.path.exists(dirname): raise errors.CliValueError( 'Directory does not exist: {0!r}'.format(self.arg)) elif os.access(self.arg, os.W_OK): return raise errors.CliValueError( 'Permission denied: {0!r}'.format(self.arg)) def __enter__(self): if self.arg == self.stdio: mode = self.kwargs.get('mode', 'r') self.f = sys.stdin if 'r' in mode else sys.stdout else: try: self.f = io.open(self.arg, **self.kwargs) except IOError as exc: raise _convert_ioerror(self.arg, exc) return self.f def __exit__(self, *exc_info): if self.arg != self.stdio or not self.keep_stdio_open: self.f.close() @contextlib.contextmanager def _silence_convert_default_warning(): with warnings.catch_warnings(): warnings.filterwarnings("ignore", "The convert_default parameter of value_converter", DeprecationWarning, r"clize\..*") yield def _conversion_filter(arg): return isinstance(arg, str) with _silence_convert_default_warning():
[docs] @parser.value_converter(name='FILE', convert_default=True, convert_default_filter=_conversion_filter) @autokwoargs(exceptions=['arg']) def file(arg=util.UNSET, stdio='-', keep_stdio_open=False, **kwargs): """Takes a file argument and provides a Python object that opens a file :: def main(in_: file(), out: file(mode='w')): with in_ as infile, out as outfile: outfile.write(infile.read()) :param stdio: If this value is passed as argument, it will be interpreted as *stdin* or *stdout* depending on the ``mode`` parameter supplied. :param keep_stdio_open: If true, does not close the file if it is *stdin* or *stdout*. Other arguments will be relayed to `io.open`. You can specify a default file name using `clize.Parameter.cli_default`:: def main(inf: (file(), Parameter.cli_default("-"))): with inf as f: print(f) .. code-block:: console $ python3 ./main.py <_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'> """ if arg is not util.UNSET: return _FileOpener(arg, kwargs, stdio, keep_stdio_open) with _silence_convert_default_warning(): return parser.value_converter( partial(_FileOpener, kwargs=kwargs, stdio=stdio, keep_stdio_open=keep_stdio_open), name='FILE', convert_default=True, convert_default_filter=_conversion_filter)
def _convert_ioerror(arg, exc): nexc = errors.ArgumentError('{0.strerror}: {1!r}'.format(exc, arg)) nexc.__cause__ = exc return nexc