bbarchivist.scripts.lazyloader.lazyloader_main()   D
last analyzed

Complexity

Conditions 13

Size

Total Lines 124
Code Lines 60

Duplication

Lines 0
Ratio 0 %

Importance

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