Passed
Pull Request — master (#559)
by Konstantin
02:09
created

ocrd.cli.resmgr   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 131
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 26
eloc 99
dl 0
loc 131
rs 10
c 0
b 0
f 0

5 Functions

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