Failed Conditions
Pull Request — master (#2076)
by Abdeali
02:11
created

ManPageFormatter._mk_name()   A

Complexity

Conditions 1

Size

Total Lines 2

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 1
dl 0
loc 2
rs 10
1
import argparse
2
import datetime
3
from distutils.core import Command
4
from distutils.errors import DistutilsOptionError
5
6
7
class BuildManPage(Command):
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable Command does not seem to be defined.
Loading history...
8
    """
9
    Add a ``build_manpage`` command  to your setup.py.
10
    To use this Command class add a command to call this class::
11
12
        # For setuptools
13
        setup(
14
              entry_points={
15
                "distutils.commands": [
16
                    "build_manpage = coalib.misc.BuildManPage:BuildManPage"
17
                ]
18
              }
19
        )
20
21
        # For distutils
22
        from coalib.misc.BuildManPage import BuildManPage
23
        setup(
24
              cmdclass={'build_manpage': BuildManPage}
25
        )
26
27
    You can then use the following setup command to produce a man page::
28
29
        $ python setup.py build_manpage --output=coala.1 \
30
            --parser=coalib.parsing.DefaultArgParser:default_arg_parser
31
32
    If automatically want to build the man page every time you invoke
33
    your build, add to your ```setup.cfg``` the following::
34
35
        [build_manpage]
36
        output = <appname>.1
37
        parser = <path_to_your_parser>
38
    """
39
    user_options = [
40
        ('output=', 'O', 'output file'),
41
        ('parser=', None, 'module path to an ArgumentParser instance'
42
         '(e.g. mymod:func, where func is a method or function which return'
43
         'an arparse.ArgumentParser instance.'),
44
    ]
45
46
    def initialize_options(self):
47
        self.output = None
48
        self.parser = None
49
50
    def finalize_options(self):
51
        if self.output is None:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable self does not seem to be defined.
Loading history...
52
            raise DistutilsOptionError('\'output\' option is required')
53
        if self.parser is None:
54
            raise DistutilsOptionError('\'parser\' option is required')
55
        mod_name, func_name = self.parser.split(':')
56
        fromlist = mod_name.split('.')
57
        mod = __import__(mod_name, fromlist=fromlist)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable mod_name does not seem to be defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable fromlist does not seem to be defined.
Loading history...
58
        self._parser = (
59
            getattr(mod, func_name)(formatter_class=ManPageFormatter))
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable ManPageFormatter does not seem to be defined.
Loading history...
60
61
        self.announce('Writing man page %s' % self.output)
62
        self._today = datetime.date.today()
63
64
    def run(self):
65
        dist = self.distribution
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable self does not seem to be defined.
Loading history...
66
        homepage = dist.get_url()
67
        maintainer = dist.get_maintainer()
68
        _license = dist.get_license()
69
        appname = self._parser.prog
70
71
        sections = {"see also": ("Online documentation: {}".format(homepage)),
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable homepage does not seem to be defined.
Loading history...
72
                    "maintainer(s)": maintainer,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable maintainer does not seem to be defined.
Loading history...
73
                    "license": _license}
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable _license does not seem to be defined.
Loading history...
74
75
        dist = self.distribution
76
        mpf = ManPageFormatter(appname,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable appname does not seem to be defined.
Loading history...
77
                               desc=dist.get_description(),
78
                               long_desc=dist.get_long_description(),
79
                               ext_sections=sections,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable sections does not seem to be defined.
Loading history...
80
                               parser=self._parser)
81
82
        formatted_man_page = mpf.format_man_page()
83
84
        with open(self.output, 'w') as man_file:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable man_file does not seem to be defined.
Loading history...
85
            man_file.write(formatted_man_page)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable formatted_man_page does not seem to be defined.
Loading history...
86
87
88
class ManPageFormatter(argparse.HelpFormatter):
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable argparse does not seem to be defined.
Loading history...
89
90
    def __init__(self,
91
                 prog,
92
                 indent_increment=2,
93
                 max_help_position=24,
94
                 width=None,
95
                 desc=None,
96
                 long_desc=None,
97
                 ext_sections=None,
98
                 parser=None):
99
        argparse.HelpFormatter.__init__(self, prog)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable prog does not seem to be defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable self does not seem to be defined.
Loading history...
100
101
        self._prog = prog
102
        self._section = 1
103
        self._today = datetime.date.today().strftime('%Y\\-%m\\-%d')
104
        self._desc = desc
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable desc does not seem to be defined.
Loading history...
105
        self._long_desc = long_desc
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable long_desc does not seem to be defined.
Loading history...
106
        self._ext_sections = ext_sections
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable ext_sections does not seem to be defined.
Loading history...
107
        self._parser = parser
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable parser does not seem to be defined.
Loading history...
108
109
    def _format_action_invocation(self, action):
110
        if not action.option_strings:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable action does not seem to be defined.
Loading history...
111
            metavar, = self._metavar_formatter(action, action.dest)(1)
112
            return metavar
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable metavar does not seem to be defined.
Loading history...
113
114
        else:
115
            # if the Optional doesn't take a value, format is:
116
            #    -s, --long
117
            if action.nargs == 0:
118
                parts = [ManPageFormatter._bold(action_str)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable action_str does not seem to be defined.
Loading history...
119
                         for action_str in action.option_strings]
120
121
            # if the Optional takes a value, format is:
122
            #    -s ARGS, --long ARGS
123
            else:
124
                default = ManPageFormatter._underline(action.dest.upper())
125
                args_string = self._format_args(action, default)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable default does not seem to be defined.
Loading history...
126
                parts = ['%s %s' % (self._bold(option_string), args_string)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable option_string does not seem to be defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable args_string does not seem to be defined.
Loading history...
127
                         for option_string in action.option_strings]
128
129
            return ', '.join(parts)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable parts does not seem to be defined.
Loading history...
130
131
    @staticmethod
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable staticmethod does not seem to be defined.
Loading history...
132
    def _markup(string):
133
        return string.replace('-', '\\-')
134
135
    @staticmethod
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable staticmethod does not seem to be defined.
Loading history...
136
    def _add_format(string, front, back):
137
        if not string.strip().startswith(front):
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable front does not seem to be defined.
Loading history...
138
            string = front + string
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable string does not seem to be defined.
Loading history...
139
        if not string.strip().endswith(back):
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable back does not seem to be defined.
Loading history...
140
            string = string + back
141
        return string
142
143
    @staticmethod
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable staticmethod does not seem to be defined.
Loading history...
144
    def _underline(string):
145
        return ManPageFormatter._add_format(string, "\\fI", "\\fR")
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable string does not seem to be defined.
Loading history...
146
147
    @staticmethod
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable staticmethod does not seem to be defined.
Loading history...
148
    def _bold(string):
149
        return ManPageFormatter._add_format(string, "\\fB", "\\fR")
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable string does not seem to be defined.
Loading history...
150
151
    def _mk_title(self):
152
        return '.TH {0} {1} {2}\n'.format(self._prog,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable self does not seem to be defined.
Loading history...
153
                                          self._section,
154
                                          self._today)
155
156
    def _mk_name(self):
157
        return '.SH NAME\n%s\n' % (self._parser.prog)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable self does not seem to be defined.
Loading history...
158
159
    def _mk_synopsis(self):
160
        self.add_usage(self._parser.usage,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable self does not seem to be defined.
Loading history...
161
                       self._parser._actions,
162
                       self._parser._mutually_exclusive_groups,
163
                       prefix='')
164
        usage = self._format_usage(None,
165
                                   self._parser._actions,
166
                                   self._parser._mutually_exclusive_groups,
167
                                   '')
168
169
        usage = usage.replace('%s ' % self._prog, '')
170
        usage = ('.SH SYNOPSIS\n \\fB%s\\fR %s\n'
171
                 % (ManPageFormatter._markup(self._prog), usage))
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable usage does not seem to be defined.
Loading history...
172
        return usage
173
174
    def _mk_description(self):
175
        if self._long_desc:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable self does not seem to be defined.
Loading history...
176
            long_desc = self._long_desc.replace('\n', '\n.br\n')
177
            return '.SH DESCRIPTION\n%s\n' % self._markup(long_desc)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable long_desc does not seem to be defined.
Loading history...
178
        else:
179
            return ''
180
181
    def _mk_options(self):
182
        formatter = self._parser._get_formatter()
183
184
        # positionals, optionals and user-defined groups
185
        for action_group in self._parser._action_groups:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable self does not seem to be defined.
Loading history...
186
            formatter.start_section(None)
187
            formatter.add_text(None)
188
            formatter.add_arguments(action_group._group_actions)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable action_group does not seem to be defined.
Loading history...
189
            formatter.end_section()
190
191
        # epilog
192
        formatter.add_text(self._parser.epilog)
193
194
        # determine help from format above
195
        return '.SH OPTIONS\n' + formatter.format_help()
196
197
    def _mk_footer(self):
198
        sections = self._ext_sections
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable self does not seem to be defined.
Loading history...
199
        if not hasattr(sections, '__iter__'):
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable sections does not seem to be defined.
Loading history...
200
            return ''
201
202
        footer = []
203
204
        for section in sorted(sections.keys()):
205
            part = ".SH {}\n {}".format(section.upper(), sections[section])
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable section does not seem to be defined.
Loading history...
206
            footer.append(part)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable part does not seem to be defined.
Loading history...
207
208
        return '\n'.join(footer)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable footer does not seem to be defined.
Loading history...
209
210
    def format_man_page(self):
211
        page = []
212
        page.append(self._mk_title())
213
        page.append(self._mk_name())
214
        page.append(self._mk_synopsis())
215
        page.append(self._mk_description())
216
        page.append(self._mk_options())
217
        page.append(self._mk_footer())
218
219
        return ''.join(page)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable page does not seem to be defined.
Loading history...
220