Welcome, guest | Sign In | My Account | Store | Cart

This is a recipe to populate command line args with the content of a file.

It is also an example of how to use the Action class from the argparse module.

I use this script in order to put frequently used options (such as for the scripts I write in config files. I created an abstract class in order to inherit from it to implement several file formats. Choice has been taken not to keep the file name in parsed args, but it can be done by adding: setattr(namespace, self.dest, values) at the end of the __call__ method.

Test functions at the end (even if the ugliest I've ever written and seen) explains the way it works.

Python, 65 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#!/usr/bin/env python3
# coding: utf-8


from abc import abstractmethod, ABCMeta
from argparse import Action, ArgumentParser

from yaml import load


class SetDefaultFromFile(Action, metaclass=ABCMeta):
    """
    Populates arguments with file contents.

    This abstract class is to be inherited per type of file read.
    """

    def __call__(self, parser, namespace, values, option_string=None):
        config = self._get_config_from_file(values)
        for key, value in config.items():
            setattr(namespace, key, value)

    @abstractmethod
    def _get_config_from_file(self, filename):
        raise NotImplementedError


class SetDefaultFromYAMLFile(SetDefaultFromFile):
    """
    Populates arguments with a YAML file contents.
    """

    def _get_config_from_file(self, filename):
        with open(filename) as f:
            config = load(f)
        return config


_TEST_FILE = 'test.yaml'
_NAME = 'spam'
_FILE_VALUE = 'eggs'
with open(_TEST_FILE, mode='w') as f:
    f.write('{}: {}'.format(_NAME, _FILE_VALUE))
_PARSER = ArgumentParser()
_PARSER.add_argument('--config', action=SetDefaultFromYAMLFile)
_PARSER.add_argument('--{}'.format(_NAME))


def test_file_content_populates_args():
    args = _PARSER.parse_args('--config {}'.format(_TEST_FILE).split())
    assert getattr(args, _NAME) == _FILE_VALUE


def test_file_content_is_erased_if_arg_given_after():
    expected = '42'
    args = _PARSER.parse_args('--config {} --spam {}'.format(_TEST_FILE,
                                                             expected).split())
    assert getattr(args, _NAME) == expected


def test_arg_is_erases_if_file_is_given_after():
    value = 12
    args = _PARSER.parse_args('--spam {} --config {}'.format(value,
                                                             _TEST_FILE).split())
    assert getattr(args, _NAME) == _FILE_VALUE
Created by obernard78+activestate on Mon, 24 Oct 2011 (MIT)
Python recipes (4591)
obernard78+activestate's recipes (1)

Required Modules

  • (none specified)

Other Information and Tasks