Passed
Pull Request — master (#559)
by Konstantin
04:33
created

ocrd.cli.resmgr.download()   F

Complexity

Conditions 20

Size

Total Lines 65
Code Lines 52

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 52
dl 0
loc 65
rs 0
c 0
b 0
f 0
cc 20
nop 5

How to fix   Long Method    Complexity   

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 ocrd.cli.resmgr.download() 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
import sys
2
from os import getcwd
3
from pathlib import Path
4
import requests
5
6
import click
7
8
from ocrd_utils import (
9
    initLogging,
10
    getLogger,
11
    XDG_CACHE_HOME,
12
    XDG_CONFIG_HOME,
13
    XDG_DATA_HOME
14
)
15
from ocrd_validators import OcrdZipValidator
16
17
from ..resource_manager import OcrdResourceManager
18
19
def print_resources(executable, reslist):
20
    print('%s' % executable)
21
    for resdict in reslist:
22
        print('- %s (%s)\n  %s' % (resdict['name'], resdict['url'], resdict['description']))
23
    print()
24
25
@click.group("resmgr")
26
def resmgr_cli():
27
    """
28
    Managing processor resources
29
    """
30
    initLogging()
31
32
@resmgr_cli.command('list-available')
33
@click.option('-e', '--executable', help='Show only resources for executable EXEC', metavar='EXEC')
34
def list_available(executable=None):
35
    """
36
    List available resources
37
    """
38
    resmgr = OcrdResourceManager()
39
    for executable, reslist in resmgr.list_available(executable):
40
        print_resources(executable, reslist)
41
42
@resmgr_cli.command('list-installed')
43
@click.option('-e', '--executable', help='Show only resources for executable EXEC', metavar='EXEC')
44
def list_installed(executable=None):
45
    """
46
    List installed resources
47
    """
48
    resmgr = OcrdResourceManager()
49
    ret = []
50
    for executable, reslist in resmgr.list_installed(executable):
51
        print_resources(executable, reslist)
52
53
@resmgr_cli.command('download')
54
@click.option('-n', '--any-url', help='Allow downloading/copying unregistered resources', is_flag=True)
55
@click.option('-o', '--overwrite', help='Overwrite existing resources', is_flag=True)
56
@click.option('-l', '--location', help='Where to store resources', type=click.Choice(['cache', 'config', 'data', 'cwd']), default='cache', show_default=True)
57
@click.argument('executable', required=True)
58
@click.argument('url_or_name', required=True)
59
def download(any_url, overwrite, location, executable, url_or_name):
60
    """
61
    Download resource URL_OR_NAME for processor EXECUTABLE.
62
63
    URL_OR_NAME can either be the ``name`` or ``url`` of a registered resource.
64
65
    If URL_OR_NAME is '*' (asterisk), download all known resources for this processor
66
67
    If ``--any-url`` is given, also accepts URL or filenames of non-registered resources for ``URL_OR_NAME``.
68
    """
69
    log = getLogger('ocrd.cli.resmgr')
70
    resmgr = OcrdResourceManager()
71
    basedir = XDG_CACHE_HOME if location == 'cache' else \
72
            XDG_DATA_HOME if location == 'data' else \
73
            XDG_CONFIG_HOME if location == 'config' else \
74
            getcwd()
75
    is_url = url_or_name.startswith('https://') or url_or_name.startswith('http://')
76
    is_filename = Path(url_or_name).exists()
77
    find_kwargs = {'executable': executable}
78
    if url_or_name != '*':
79
        find_kwargs['url' if is_url else 'name'] = url_or_name
80
    reslist = resmgr.find_resources(**find_kwargs)
81
    if not reslist:
82
        log.info("No resources found in registry")
83
        if any_url and (is_url or is_filename):
84
            log.info("%s unregistered resource %s" % ("Downloading" if is_url else "Copying", url_or_name))
85
            if is_url:
86
                with requests.get(url_or_name, stream=True) as r:
87
                    content_length = int(r.headers.get('content-length'))
88
            else:
89
                url_or_name = str(Path(url_or_name).resolve())
90
                content_length = Path(url_or_name).stat().st_size
91
            with click.progressbar(length=content_length, label="Downloading" if is_url else "Copying") as bar:
92
                fpath = resmgr.download(
93
                    executable,
94
                    url_or_name,
95
                    overwrite=overwrite,
96
                    basedir=basedir,
97
                    progress_cb=lambda delta: bar.update(delta))
98
            log.info("%s %s to %s" % ("Downloaded" if is_url else "Copied", url_or_name, fpath))
99
            log.info("Use in parameters as '%s'" % fpath.name)
100
        else:
101
            sys.exit(1)
102
    else:
103
        for _, resdict in reslist:
104
            log.info("Downloading resource %s" % resdict)
105
            with click.progressbar(length=resdict['size']) as bar:
106
                fpath = resmgr.download(
107
                    executable,
108
                    resdict['url'],
109
                    name=resdict['name'],
110
                    resource_type=resdict['type'],
111
                    path_in_archive=resdict.get('path_in_archive', '.'),
112
                    overwrite=overwrite,
113
                    basedir=basedir,
114
                    progress_cb=lambda delta: bar.update(delta)
115
                )
116
            log.info("Downloaded %s to %s" % (resdict['url'], fpath))
117
            log.info("Use in parameters as '%s'" % resmgr.parameter_usage(resdict['name'], usage=resdict['parameter_usage']))
118
119