summaryrefslogtreecommitdiff
path: root/mailman/options.py
blob: 317ff8d8d899b1aa5e9b2f3757b016a1082058e8 (plain)
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# Copyright (C) 2008 by the Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
# USA.

"""Common argument parsing."""

__metaclass__ = type
__all__ = [
    'Options',
    'SingleMailingListOptions',
    ]


import sys

from copy import copy
from optparse import Option, OptionParser, OptionValueError

from mailman.version import MAILMAN_VERSION
from mailman.configuration import config
from mailman.i18n import _
from mailman.initialize import initialize



def check_unicode(option, opt, value):
    if isinstance(value, unicode):
        return value
    try:
        return value.decode(sys.getdefaultencoding())
    except UnicodeDecodeError:
        raise OptionValueError(
            'option %s: Cannot decode: %r' % (opt, value))


def check_yesno(option, opt, value):
    value = value.lower()
    if value not in ('yes', 'no', 'y', 'n'):
        raise OptionValueError('option s: invalid: %r' % (opt, value))
    return value[0] == 'y'


class MailmanOption(Option):
    """Extension types for unicode options."""
    TYPES = Option.TYPES + ('unicode', 'yesno')
    TYPE_CHECKER = copy(Option.TYPE_CHECKER)
    TYPE_CHECKER['unicode'] = check_unicode
    TYPE_CHECKER['yesno'] = check_yesno



class Options:
    """Common argument parser."""

    # Subclasses should override.
    usage = None

    def __init__(self):
        self.parser = OptionParser(version=MAILMAN_VERSION,
                                   option_class=MailmanOption,
                                   usage=self.usage)
        self.add_common_options()
        self.add_options()
        options, arguments = self.parser.parse_args()
        self.options = options
        self.arguments = arguments
        # Also, for convenience, place the options in the configuration file
        # because occasional global uses are necessary.
        config.options = self

    def add_options(self):
        """Allow the subclass to add its own specific arguments."""
        pass

    def sanity_check(self):
        """Allow subclasses to do sanity checking of arguments."""
        pass

    def add_common_options(self):
        """Add options common to all scripts."""
        self.parser.add_option(
            '-C', '--config',
            help=_('Alternative configuration file to use'))

    def initialize(self, propagate_logs=False):
        """Initialize the configuration system.

        After initialization of the configuration system, perform sanity
        checks.  We do it in this order because some sanity checks require the
        configuration to be initialized.

        :param propagate_logs: Flag specifying whether log messages in
            sub-loggers should be propagated to the master logger (and hence
            to the root logger).
        """
        initialize(self.options.config, propagate_logs=propagate_logs)
        self.sanity_check()



class SingleMailingListOptions(Options):
    """A helper for specifying the mailing list on the command line."""

    def add_options(self):
        self.parser.add_option(
            '-l', '--listname',
            type='unicode', help=_('The mailing list name'))
        super(SingleMailingListOptions, self).add_options()


class MultipleMailingListOptions(Options):
    """A helper for specifying multiple mailing lists on the command line."""

    def add_options(self):
        self.parser.add_option(
            '-l', '--listname',
            default=[], action='append', dest='listnames', type='unicode',
            help=("""\
A mailing list name.  It is okay to have multiple --listname options."""))