show_langlist()   F
last analyzed

Complexity

Conditions 10

Size

Total Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 10
c 4
b 0
f 0
dl 0
loc 38
rs 3.1304

How to fix   Complexity   

Complexity

Complex classes like show_langlist() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
#
2
# Copyright (c) 2015 SUSE Linux GmbH
3
#
4
# This program is free software; you can redistribute it and/or
5
# modify it under the terms of version 3 of the GNU General Public License as
6
# published by the Free Software Foundation.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, contact SUSE LLC.
15
#
16
# To contact SUSE about this file by physical or electronic mail,
17
# you may find current contact information at www.suse.com
18
19
20
import os
21
import os.path
22
import re
23
import sys
24
import urllib.request
25
from glob import glob
26
27
from ..core import BT_ELEMENTLIST
28
from ..core import DEFAULT_DM_PROPERTIES
29
from ..core import DEFAULTSUBCOMMANDS
30
from ..core import LANGUAGES
31
from ..core import STATUSFLAGS
32
from ..core import ReturnCodes
33
from ..logmanager import log
34
from ..logmanager import logmgr_flog
35
36
37
def show_langlist(columns=None, padding=2):
38
    """Prints all supported languages
39
40
    :param int columns: Maximum number of characters in a column;
41
                        None to fill the current terminal window
42
    :param int padding: space from longest entry to border
43
    """
44
45
    try:
46
        from shutil import get_terminal_size
47
    except ImportError:
48
        import os
49
50
        def get_terminal_size(fallback=(80, 24)):
51
            return os.terminal_size(fallback)
52
53
    maxl = max([len(i) for i in LANGUAGES])
54
55
    if columns is None or columns < maxl:
56
        columns = get_terminal_size().columns
57
    length = len(LANGUAGES)
58
    rowwidth = maxl + padding + 1
59
    divisor = columns // rowwidth
60
    maxline = divisor * rowwidth
61
62
    fmt="".join(["{{:<{}}}|".format(maxl + padding) for _ in range(divisor)])# flake8: noqa
63
    line = "-"*maxline
64
    print(line)
65
    for start, stop in zip(range(0, length, divisor),
66
                           range(divisor, length+divisor, divisor)):
67
        x = list(LANGUAGES[start:stop])
68
        if len(x) < divisor:
69
            for i in range(divisor - len(x)):
70
                x.append("")
71
        print(fmt.format(*x))
72
    print(line)
73
74
    sys.exit(ReturnCodes.E_OK)
75
76
77
def populate_properties(args):
78
    """Populate args.properties from "standard" options
79
80
    :param argparse.Namespace args:
81
    :return: list of property=value items
82
    :rtype: list
83
    """
84
85
    result = []
86
    for prop in DEFAULT_DM_PROPERTIES:
87
        proparg = prop.replace("/", "_")
88
        if hasattr(args, proparg) and getattr(args, proparg) is not None:
89
            result.append("{}={}".format(prop, getattr(args, proparg)))
90
91
    return result
92
93
94
def populate_bugtracker_properties(args):
95
    """Populate args.bugtracker_* from "standard" options
96
97
    :param argparse.Namespace args:
98
    :return: list of property=value items
99
    :rtype: list
100
    """
101
102
    result = []
103
    for prop in BT_ELEMENTLIST:
104
        proparg = prop.replace("/", "_")
105
        if hasattr(args, proparg) and getattr(args, proparg) is not None:
106
            result.append("{}={}".format(prop, getattr(args, proparg)))
107
108
    return result
109
110
111
def clean_filelist(args):
112
    """Clean the file list from unwanted directory names
113
114
    :param argparse.Namespace args: Parsed arguments
115
    """
116
    # Remove any directories from our files list
117
    allfiles = args.files[:]
118
    args.files = [f for f in args.files if not os.path.isdir(f)]
119
    diff = list(set(allfiles) - set(args.files))
120
121
    # This just disturbs especially if we want to use DocManager in scripts
122
    #if diff:
123
    #    print("Ignoring the following directories:", ", ".join(diff))
124
125
126
def fix_properties(args):
127
    """Make different property styles consistent
128
129
    :param argparse.Namespace args: Parsed arguments
130
    """
131
    # Handle the different styles with -p foo and -p foo,bar
132
    # Needed to split the syntax 'a,b', 'a;b' or 'a b' into a list
133
    # regardless of the passed arguments
134
    _props = []
135
    # Use an empty list when args.properties = None
136
    args.properties = [] if args.properties is None else args.properties
137
    for item in args.properties:
138
        repl = re.split("[,;]", item)
139
        _props.extend(repl)
140
    args.properties = _props
141
142
    # Fill "standard" properties (like status) also into properties list:
143
    if args.action in ("s", "set"):
144
        args.properties.extend(populate_properties(args))
145
        args.properties.extend(populate_bugtracker_properties(args))
146
147
148
def is_alias(subcmd):
149
    """Check if subcmd is an alias
150
    :rtype: bool
151
    """
152
    return subcmd not in DEFAULTSUBCOMMANDS
153
154
155
def parse_alias_value(value):
156
    """Parse pre defined constants
157
158
    :param str value: alias
159
    :return: parsed alias
160
    :rtype: str
161
    """
162
    return value.replace("{USER}", os.environ['USER'])
163
164
165
def input_format_check(args):
166
    """Checks if the given arguments have a correct value
167
168
    :param object args: Arguments object from argparser
169
    """
170
    logmgr_flog()
171
172
    if hasattr(args, 'status') and args.status is not None:
173
        if args.status not in STATUSFLAGS:
174
            print("Value of 'status' property is incorrect. "
175
                  "Expecting one of these values: "
176
                  "{}".format(", ".join(STATUSFLAGS)))
177
            sys.exit(ReturnCodes.E_WRONG_INPUT_FORMAT)
178
179
    if hasattr(args, 'deadline') and args.deadline is not None:
180
        match = re.match("^[0-9]{4}\-[0-9]{2}\-[0-9]{2}$", args.deadline)
181
        if match is None:
182
            print("Value of 'deadline' is incorrect. "
183
                  "Use this date format: YYYY-MM-DD")
184
            sys.exit(ReturnCodes.E_WRONG_INPUT_FORMAT)
185
186
    if hasattr(args, 'priority') and args.priority is not None:
187
        errmsg = ("Value of 'priority' is incorrect. "
188
                  "Expecting a value between 1 and 10.")
189
190
        if not args.priority.isnumeric():
191
            print(errmsg)
192
            sys.exit(ReturnCodes.E_WRONG_INPUT_FORMAT)
193
194
        args.priority = int(args.priority)
195
        if args.priority < 1 or args.priority > 10:
196
            print(errmsg)
197
            sys.exit(ReturnCodes.E_WRONG_INPUT_FORMAT)
198
199
    if hasattr(args, 'translation') and args.translation is not None:
200
        values = ('yes', 'no')
201
        if args.translation not in values:
202
            print("Value of 'translation' is incorrect. "
203
                  "Expecting one of these values: yes or no")
204
            sys.exit(ReturnCodes.E_WRONG_INPUT_FORMAT)
205
206
    if hasattr(args, 'languages') and args.languages is not None:
207
        for i in args.languages.split(","):
208
            if i not in LANGUAGES:
209
                print("Value of 'languages' is incorrect. "
210
                      "Language code '{}' is not supported. "
211
                      "Type 'docmanager --langlist' to see "
212
                      "all supported language codes.".format(i))
213
                sys.exit(ReturnCodes.E_WRONG_INPUT_FORMAT)
214
215
    if hasattr(args, 'repository') and args.repository is not None:
216
        request = None
217
        try:
218
            request = urllib.request.urlopen(args.repository)
219
        except ValueError:
220
            print("Value of 'repository' is incorrect. "
221
                  "The value is not a URL.")
222
            sys.exit(ReturnCodes.E_WRONG_INPUT_FORMAT)
223
        except urllib.error.URLError as err:
224
            if hasattr(err, 'code') and err.code is not None:
225
                if err.code is not 200:
226
                    log.warn("The remote server returns an error code "
227
                             "for this request: {} - Please double check if "
228
                             "the URL is correct. Nevertheless the URL will "
229
                             "be written into the "
230
                             "given files.".format(err.code))
231
            else:
232
                log.warn("The given URL '{}' seems to be invalid or the "
233
                         "remote server is not online. Please double "
234
                         "check if the URL is correct. Nevertheless the "
235
                         "URL will be written into the "
236
                         "given files.".format(args.repository))
237
238
        if hasattr(request, 'close'):
239
            request.close()
240
241
242
def fix_filelist(files):
243
    """Replaces * with all files in a directory (shell like)
244
245
    :param list files: file list from args.files
246
    """
247
248
    if files:
249
        tmpfiles = files[:]
250
        files.clear()
251
252
        for idx, i in enumerate(tmpfiles[:]):
253
            filelist = glob(i)
254
            if filelist:
255
                for x in filelist:
256
                    if not os.path.exists(x):
257
                        log.error("Cannot find file {!r}!".format(x))
258
                        sys.exit(ReturnCodes.E_FILE_NOT_FOUND)
259
260
                    files.append(x)
261
            else:
262
                if not os.path.exists(i):
263
                    log.error("Cannot find file {!r}!".format(i))
264
                    sys.exit(ReturnCodes.E_FILE_NOT_FOUND)
265
266
def fix_attributes(args):
267
    """Make different attributes styles consistent
268
269
    :param argparse.Namespace args: Parsed arguments
270
    """
271
    # Handle the different styles with -a foo and -a foo,bar
272
    # Needed to split the syntax 'a,b', 'a;b' or 'a b' into a list
273
    # regardless of the passed arguments
274
    _attrs = []
275
    # Use an empty list when args.attributes = None or if args.attributes does not exists
276
    args.attributes = [] if not hasattr(args, 'attributes') or args.attributes is None else args.attributes
277
    for item in args.attributes:
278
        repl = re.split("[,;]", item)
279
        _attrs.extend(repl)
280
    args.attributes = _attrs
281