Test Failed
Push — master ( 33284b...c56792 )
by John
02:53
created

bbarchivist.scripts.lazyloader.lazyloader_main()   F

Complexity

Conditions 15

Size

Total Lines 124
Code Lines 60

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 15
eloc 60
nop 9
dl 0
loc 124
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like bbarchivist.scripts.lazyloader.lazyloader_main() 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.

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
#!/usr/bin/env python3
2
"""Create one autoloader for personal use."""
3
4
import os  # path work
5
import subprocess  # autoloader running
6
import sys  # load arguments
7
8
import requests  # session
9
from bbarchivist import barutils  # file operations
10
from bbarchivist import bbconstants  # constants/versions
11
from bbarchivist import decorators  # timer
12
from bbarchivist import loadergen  # cap wrapper
13
from bbarchivist import networkutils  # download/lookup
14
from bbarchivist import scriptutils  # script stuff
15
from bbarchivist import utilities  # input validation
16
17
__author__ = "Thurask"
18
__license__ = "WTFPL v2"
19
__copyright__ = "2015-2018 Thurask"
20
21
22
@decorators.timer
23
def grab_args():
24
    """
25
    Parse arguments from argparse/questionnaire.
26
27
    Invoke :func:`lazyloader.lazyloader_main` with arguments.
28
    """
29
    if len(sys.argv) > 1:
30
        argflags = ("folder", "osr")
31
        parser = scriptutils.default_parser("bb-lazyloader", "Create one autoloader", argflags)
32
        devgroup = parser.add_argument_group("devices", "Device to load (one required)")
33
        compgroup = devgroup.add_mutually_exclusive_group()
34
        compgroup.add_argument(
35
            "--stl100-1",
36
            dest="device",
37
            help="STL100-1",
38
            action="store_const",
39
            const=0)
40
        compgroup.add_argument(
41
            "--stl100-x",
42
            dest="device",
43
            help="STL100-2/3, P'9982",
44
            action="store_const",
45
            const=1)
46
        compgroup.add_argument(
47
            "--stl100-4",
48
            dest="device",
49
            help="STL100-4",
50
            action="store_const",
51
            const=2)
52
        compgroup.add_argument(
53
            "--q10",
54
            dest="device",
55
            help="Q10, Q5, P'9983",
56
            action="store_const",
57
            const=3)
58
        compgroup.add_argument(
59
            "--z30",
60
            dest="device",
61
            help="Z30, Classic, Leap",
62
            action="store_const",
63
            const=4)
64
        compgroup.add_argument(
65
            "--z3",
66
            dest="device",
67
            help="Z3",
68
            action="store_const",
69
            const=5)
70
        compgroup.add_argument(
71
            "--passport",
72
            dest="device",
73
            help="Passport",
74
            action="store_const",
75
            const=6)
76
        parser.add_argument(
77
            "--run-loader",
78
            dest="autoloader",
79
            help="Run autoloader after creation",
80
            action="store_true",
81
            default=False)
82
        parser.add_argument(
83
            "-n",
84
            "--no-download",
85
            dest="download",
86
            help="Don't download files",
87
            action="store_false",
88
            default=True)
89
        parser.add_argument(
90
            "-r",
91
            "--radiosw",
92
            dest="altsw",
93
            metavar="SW",
94
            help="Radio software version; use without software to guess",
95
            nargs="?",
96
            const="checkme",
97
            default=None)
98
        parser.add_argument(
99
            "-c",
100
            "--core",
101
            dest="core",
102
            help="Make core/radio loader",
103
            default=False,
104
            action="store_true")
105
        parser.set_defaults(device=None)
106
        args = parser.parse_args(sys.argv[1:])
107
        execute_args(args)
108
    else:
109
        questionnaire()
110
111
112
def execute_args(args):
113
    """
114
    Get args and decide what to do with them.
115
116
    :param args: Arguments.
117
    :type args: argparse.Namespace
118
    """
119
    args.folder = scriptutils.generate_workfolder(args.folder)
120
    if not utilities.is_windows():
121
        args.autoloader = False
122
    scriptutils.arg_verify_none(args.os, "No OS specified!")
123
    scriptutils.arg_verify_none(args.device, "No device specified!")
124
    lazyloader_main(args.device, args.os, args.radio, args.swrelease, args.folder, args.autoloader, args.download, args.altsw, args.core)
125
126
127
def questionnaire_getversions():
128
    """
129
    Get OS, radio, and software versions.
130
    """
131
    while True:
132
        osversion = input("OS VERSION (REQUIRED): ")
133
        if osversion:
134
            break
135
    radioversion = input("RADIO VERSION (PRESS ENTER TO GUESS): ")
136
    softwareversion = input("OS SOFTWARE RELEASE (PRESS ENTER TO GUESS): ")
137
    return osversion, radioversion, softwareversion
138
139
140
def questionnaire_check(softwareversion, radioversion):
141
    """
142
    Check software and radio versions.
143
144
    :param softwareversion: Software version, 10.x.y.zzzz.
145
    :type softwareversion: str
146
147
    :param radioversion: Radio version, 10.x.y.zzzz.
148
    :type radioversion: str
149
    """
150
    if not softwareversion:
151
        softwareversion = None
152
    if not radioversion:
153
        radioversion = None
154
        altsw = None
155
    else:
156
        radioversion, altsw = questionnaire_radiocheck(radioversion, altsw)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable altsw does not seem to be defined.
Loading history...
157
    return softwareversion, radioversion, altsw
158
159
160
def questionnaire_radiocheck(radioversion, altsw):
161
    """
162
    Get radio information in working order.
163
164
    :param radioversion: Radio version, 10.x.y.zzzz.
165
    :type radioversion: str
166
167
    :param altsw: Radio software release, if not the same as OS.
168
    :type altsw: str
169
    """
170
    altcheck = utilities.i2b("USING ALTERNATE RADIO (Y/N)?: ")
171
    if altcheck:
172
        altsw = input("RADIO SOFTWARE RELEASE (PRESS ENTER TO GUESS): ")
173
        if not altsw:
174
            altsw = "checkme"
175
    return radioversion, altsw
176
177
178
def questionnaire_devices():
179
    """
180
    Ask about which device this script is to be run for.
181
    """
182
    print("DEVICES:")
183
    devlist = ["0=STL100-1", "1=STL100-2/3/P9982", "2=STL100-4", "3=Q10/Q5/P9983", "4=Z30/CLASSIC/LEAP", "5=Z3", "6=PASSPORT"]
184
    utilities.lprint(devlist)
185
    while True:
186
        device = int(input("SELECTED DEVICE: "))
187
        if not 0 <= device <= len(devlist) - 1:
188
            continue
189
        else:
190
            break
191
    return device
192
193
194
def questionnaire_loader():
195
    """
196
    Ask about whether to run an autoloader.
197
    """
198
    if utilities.is_windows():
199
        autoloader = utilities.i2b("RUN AUTOLOADER - WILL WIPE YOUR DEVICE! (Y/N)?: ")
200
    else:
201
        autoloader = False
202
    return autoloader
203
204
205
def questionnaire():
206
    """
207
    Questions to ask if no arguments given.
208
    """
209
    localdir = os.getcwd()
210
    osver, radiover, swver = questionnaire_getversions()
211
    swver, radiover, altsw = questionnaire_check(swver, radiover)
212
    device = questionnaire_devices()
213
    autoloader = questionnaire_loader()
214
    print(" ")
215
    lazyloader_main(device, osver, radiover, swver, localdir, autoloader, True, altsw, False)
216
217
218
def lazyloader_main(device, osversion, radioversion=None, softwareversion=None, localdir=None, autoloader=False, download=True, altsw=None, core=False):
2 ignored issues
show
best-practice introduced by
Too many arguments (9/5)
Loading history...
Comprehensibility introduced by
This function exceeds the maximum number of variables (30/15).
Loading history...
219
    """
220
    Wrap the tools necessary to make one autoloader.
221
222
    :param device: Device family to create loader for.
223
    :type device: int
224
225
    :param osversion: OS version, 10.x.y.zzzz.
226
    :type osversion: str
227
228
    :param radioversion: Radio version, 10.x.y.zzzz.
229
    :type radioversion: str
230
231
    :param softwareversion: Software version, 10.x.y.zzzz.
232
    :type softwareversion: str
233
234
    :param localdir: Working path. Default is local dir.
235
    :type localdir: str
236
237
    :param autoloader: Whether to run loader. Default is false. Windows-only.
238
    :type autoloader: bool
239
240
    :param download: Whether to download files. Default is true.
241
    :type download: bool
242
243
    :param altsw: Radio software release, if not the same as OS.
244
    :type altsw: str
245
246
    :param core: Whether to create a core/radio loader. Default is false.
247
    :type core: bool
248
    """
249
    radioversion = scriptutils.return_radio_version(osversion, radioversion)
250
    softwareversion, swc = scriptutils.return_sw_checked(softwareversion, osversion)
251
    if altsw == "checkme":
252
        altsw, altchecked = scriptutils.return_radio_sw_checked(altsw, radioversion)
253
    scriptutils.standard_preamble("lazyloader", osversion, softwareversion, radioversion, altsw)
254
    print("DEVICE: {0}".format(bbconstants.DEVICES[device]))
255
256
    # Make dirs
257
    bd_o, bd_r, ld_o, ld_r, zd_o, zd_r = barutils.make_dirs(localdir, osversion, radioversion)
258
    osurl = radiourl = None
259
260
    # Create download URLs
261
    baseurl = utilities.create_base_url(softwareversion)
262
    if altsw:
263
        alturl = utilities.create_base_url(altsw)
264
    osurl, radiourl = utilities.generate_lazy_urls(softwareversion, osversion, radioversion, device)
265
    if altsw:
266
        radiourl = radiourl.replace(baseurl, alturl)
1 ignored issue
show
introduced by
The variable alturl does not seem to be defined in case altsw on line 262 is False. Are you sure this can never be the case?
Loading history...
267
    if core:
268
        osurl = osurl.replace(".desktop", "")
269
270
    #Terminate if device is STL100-1 and OS >= 10.3.3
271
    splitos = [int(i) for i in osversion.split(".")]
272
    if device == 0 and utilities.newer_103(splitos, 3):
273
        print("STL100-1 UNSUPPORTED IN 10.3.3+!")
274
        print("\nEXITING...")
275
        raise SystemExit
276
277
    if download:
278
        # Check availability of software releases
279
        scriptutils.check_sw(baseurl, softwareversion, swc)
280
        if altsw:
281
            scriptutils.check_radio_sw(alturl, altsw, altchecked)
1 ignored issue
show
introduced by
The variable altchecked does not seem to be defined in case altsw == "checkme" on line 251 is False. Are you sure this can never be the case?
Loading history...
282
283
        # Check availability of OS, radio
284
        scriptutils.check_os_single(osurl, osversion, device)
285
        radiourl, radioversion = scriptutils.check_radio_single(radiourl, radioversion)
286
    dllist = [osurl, radiourl]
287
288
    # Check cached
289
    osfile = os.path.join(localdir, bd_o, os.path.basename(osurl))
290
    radfile = os.path.join(localdir, bd_r, os.path.basename(radiourl))
291
292
    if download:
293
        # Download files
294
        print("DOWNLOADING...")
295
        sess = requests.Session()
296
        networkutils.download_bootstrap(dllist, outdir=localdir, workers=2, session=sess)
297
    elif all(os.path.exists(x) for x in [osfile, radfile]):
298
        # Already downloaded in previous session
299
        print("USING CACHED OS/RADIO...")
300
        barutils.replace_bar_pair(localdir, osfile, radfile)
301
302
    # Test bar files
303
    scriptutils.test_bar_files(localdir, dllist)
304
305
    # Extract bar files
306
    print("EXTRACTING...")
307
    barutils.extract_bars(localdir)
308
309
    # Test signed files
310
    scriptutils.test_signed_files(localdir)
311
312
    # Move bar files
313
    print("MOVING BAR FILES...")
314
    barutils.move_bars(localdir, bd_o, bd_r)
315
316
    # Generate loader
317
    altradio = radioversion if altsw else None
318
    loadergen.generate_lazy_loader(osversion, device, os.path.abspath(localdir), altradio, core)
319
320
    # Test loader
321
    suffix = loadergen.format_suffix(bool(altradio), altradio, core)
322
    loadername = loadergen.generate_filename(device, osversion, suffix)
323
    loaderpath = os.path.join(localdir, loadername)
324
    scriptutils.test_single_loader(loaderpath)
325
326
    # Remove signed files
327
    print("REMOVING SIGNED FILES...")
328
    barutils.remove_signed_files(localdir)
329
330
    # Move loaders
331
    print("MOVING LOADERS...")
332
    barutils.move_loaders(localdir, ld_o, ld_r, zd_o, zd_r)
333
    loadername = os.path.join(ld_o, loadername)
334
335
    # Delete empty folders
336
    print("REMOVING EMPTY FOLDERS...")
337
    barutils.remove_empty_folders(localdir)
338
339
    if autoloader:
340
        subprocess.call(loadername)
341
    print("\nFINISHED!!!")
342
343
344
if __name__ == "__main__":
345
    grab_args()
346
    decorators.enter_to_exit(True)
347