Passed
Push — master ( f9ce65...f07e05 )
by Konstantin
03:14
created

ocrd.cli.ocrd_tool.ocrd_tool_dump()   A

Complexity

Conditions 1

Size

Total Lines 4
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nop 1
1
"""
2
OCR-D CLI: ocrd-tool.json management
3
4
.. click:: ocrd.cli.ocrd_tool:ocrd_tool_cli
5
    :prog: ocrd ocrd-tool
6
    :nested: full
7
8
"""
9
from inspect import getmodule
10
from json import dumps
11
import codecs
12
import sys
13
import os
14
import click
15
16
from ocrd.decorators import parameter_option, parameter_override_option
17
from ocrd.processor import Processor
18
from ocrd_utils import (
19
    set_json_key_value_overrides,
20
    parse_json_string_or_file,
21
    parse_json_string_with_comments as loads
22
)
23
from ocrd_validators import ParameterValidator, OcrdToolValidator
24
25
class OcrdToolCtx():
26
27
    def __init__(self, filename):
28
        self.filename = filename
29
        with codecs.open(filename, encoding='utf-8') as f:
30
            self.content = f.read()
31
            # perhaps the validator should _always_ run (for default expansion)
32
            # so validate command only for the report?
33
            self.json = loads(self.content)
34
        self.tool_name = ''
35
36
        class BashProcessor(Processor):
37
            @property
38
            def metadata(inner_self): # pylint: disable=no-self-argument,arguments-renamed
39
                return self.json
40
            @property
41
            def executable(inner_self): # pylint: disable=no-self-argument,arguments-renamed
42
                return self.tool_name
43
            @property
44
            def moduledir(inner_self): # pylint: disable=no-self-argument,arguments-renamed
45
                return os.path.dirname(self.filename)
46
            # set docstrings to empty
47
            __doc__ = None
48
            # HACK: override the module-level docstring, too
49
            getmodule(OcrdToolCtx).__doc__ = None
50
            def process(inner_self): # pylint: disable=no-self-argument,arguments-renamed
51
                return super()
52
53
        self.processor = BashProcessor
54
55
pass_ocrd_tool = click.make_pass_decorator(OcrdToolCtx)
56
57
# ----------------------------------------------------------------------
58
# ocrd ocrd-tool
59
# ----------------------------------------------------------------------
60
61
@click.group('ocrd-tool', help='Work with ocrd-tool.json JSON_FILE')
62
@click.argument('json_file')
63
@click.pass_context
64
def ocrd_tool_cli(ctx, json_file):
65
    ctx.obj = OcrdToolCtx(json_file)
66
67
# ----------------------------------------------------------------------
68
# ocrd ocrd-tool version
69
# ----------------------------------------------------------------------
70
71
@ocrd_tool_cli.command('version', help='Version of ocrd-tool.json')
72
@pass_ocrd_tool
73
def ocrd_tool_version(ctx):
74
    print(ctx.json['version'])
75
76
# ----------------------------------------------------------------------
77
# ocrd ocrd-tool validate
78
# ----------------------------------------------------------------------
79
80
@ocrd_tool_cli.command('validate', help='Validate an ocrd-tool.json')
81
@pass_ocrd_tool
82
def ocrd_tool_validate(ctx):
83
    report = OcrdToolValidator.validate(ctx.json)
84
    print(report.to_xml())
85
    if not report.is_valid:
86
        return 128
87
88
# ----------------------------------------------------------------------
89
# ocrd ocrd-tool list-tools
90
# ----------------------------------------------------------------------
91
92
@ocrd_tool_cli.command('list-tools', help="List tools")
93
@pass_ocrd_tool
94
def ocrd_tool_list(ctx):
95
    for tool in ctx.json['tools']:
96
        print(tool)
97
98
# ----------------------------------------------------------------------
99
# ocrd ocrd-tool dump-tools
100
# ----------------------------------------------------------------------
101
102
@ocrd_tool_cli.command('dump-tools', help="Dump tools")
103
@pass_ocrd_tool
104
def ocrd_tool_dump(ctx):
105
    print(dumps(ctx.json['tools'], indent=True))
106
107
# ----------------------------------------------------------------------
108
# ocrd ocrd-tool tool
109
# ----------------------------------------------------------------------
110
111
@ocrd_tool_cli.group('tool', help='Work with a single tool TOOL_NAME')
112
@click.argument('tool_name')
113
@pass_ocrd_tool
114
def ocrd_tool_tool(ctx, tool_name):
115
    if tool_name not in ctx.json['tools']:
116
        raise Exception("No such tool: %s" % tool_name)
117
    ctx.tool_name = tool_name
118
119
# ----------------------------------------------------------------------
120
# ocrd ocrd-tool tool description
121
# ----------------------------------------------------------------------
122
123
@ocrd_tool_tool.command('description', help="Describe tool")
124
@pass_ocrd_tool
125
def ocrd_tool_tool_description(ctx):
126
    print(ctx.json['tools'][ctx.tool_name]['description'])
127
128
@ocrd_tool_tool.command('list-resources', help="List tool's file resources")
129
@pass_ocrd_tool
130
def ocrd_tool_tool_list_resources(ctx):
131
    ctx.processor(None).list_resources()
132
133
@ocrd_tool_tool.command('resolve-resource', help="Get a tool's file resource full path name")
134
@click.argument('res_name')
135
@pass_ocrd_tool
136
def ocrd_tool_tool_resolve_resource(ctx, res_name):
137
    print(ctx.processor(None).resolve_resource(res_name))
138
139
@ocrd_tool_tool.command('show-resource', help="Dump a tool's file resource")
140
@click.argument('res_name')
141
@pass_ocrd_tool
142
def ocrd_tool_tool_show_resource(ctx, res_name):
143
    ctx.processor(None).show_resource(res_name)
144
145
@ocrd_tool_tool.command('help', help="Generate help for processors")
146
@click.argument('subcommand', required=False)
147
@pass_ocrd_tool
148
def ocrd_tool_tool_params_help(ctx, subcommand):
149
    ctx.processor(None).show_help(subcommand=subcommand)
150
151
# ----------------------------------------------------------------------
152
# ocrd ocrd-tool tool categories
153
# ----------------------------------------------------------------------
154
155
@ocrd_tool_tool.command('categories', help="Categories of tool")
156
@pass_ocrd_tool
157
def ocrd_tool_tool_categories(ctx):
158
    print('\n'.join(ctx.json['tools'][ctx.tool_name]['categories']))
159
160
# ----------------------------------------------------------------------
161
# ocrd ocrd-tool tool steps
162
# ----------------------------------------------------------------------
163
164
@ocrd_tool_tool.command('steps', help="Steps of tool")
165
@pass_ocrd_tool
166
def ocrd_tool_tool_steps(ctx):
167
    print('\n'.join(ctx.json['tools'][ctx.tool_name]['steps']))
168
169
# ----------------------------------------------------------------------
170
# ocrd ocrd-tool tool dump
171
# ----------------------------------------------------------------------
172
173
@ocrd_tool_tool.command('dump', help="Dump JSON of tool")
174
@pass_ocrd_tool
175
def ocrd_tool_tool_dump(ctx):
176
    print(dumps(ctx.json['tools'][ctx.tool_name], indent=True))
177
178
# ----------------------------------------------------------------------
179
# ocrd ocrd-tool tool parse-params
180
# ----------------------------------------------------------------------
181
182
@ocrd_tool_tool.command('parse-params')
183
@parameter_option
184
@parameter_override_option
185
@click.option('-j', '--json', help='Output JSON instead of shell variables', is_flag=True, default=False)
186
@pass_ocrd_tool
187
def ocrd_tool_tool_parse_params(ctx, parameter, parameter_override, json):
188
    """
189
    Parse parameters with fallback to defaults and output as shell-eval'able assignments to params var.
190
    """
191
    parameter = set_json_key_value_overrides(parse_json_string_or_file(*parameter), *parameter_override)
192
    parameterValidator = ParameterValidator(ctx.json['tools'][ctx.tool_name])
193
    report = parameterValidator.validate(parameter)
194
    if not report.is_valid:
195
        print(report.to_xml())
196
        sys.exit(1)
197
    if json:
198
        print(dumps(parameter))
199
    else:
200
        for k in parameter:
201
            print('params["%s"]="%s"' % (k, parameter[k]))
202