diff --git a/src/ocrd/cli/__init__.py b/src/ocrd/cli/__init__.py index 9e8a37b8bf..eb70d7edfc 100644 --- a/src/ocrd/cli/__init__.py +++ b/src/ocrd/cli/__init__.py @@ -16,7 +16,7 @@ def command_with_replaced_help(*replacements): class CommandWithReplacedHelp(click.Command): def get_help(self, ctx): - newhelp = super().get_help(ctx) + newhelp : str = super().get_help(ctx) for replacement in replacements: newhelp = re.sub(*replacement, newhelp) # print(newhelp) diff --git a/src/ocrd_utils/config.py b/src/ocrd_utils/config.py index 36399870e2..16c9eb02e8 100644 --- a/src/ocrd_utils/config.py +++ b/src/ocrd_utils/config.py @@ -21,7 +21,7 @@ def _parser_boolean(val): class OcrdEnvVariable(): - def __init__(self, name, description, parser=str, validator=lambda val: True, default=[False, None]): + def __init__(self, name, description, parser=str, validator=lambda _: True, default=[False, None]): """ An environment variable for use in OCR-D. @@ -47,10 +47,19 @@ def __str__(self): return f'{self.name}: {self.description}' def describe(self, wrap_text=True, indent_text=True): + """ + Output help information on a config option. + + If ``option.description`` is a multiline string with complex formatting + (e.g. markdown lists), replace empty lines with ``\b`` and set + ``wrap_text`` to ``False``. + """ desc = self.description if self.has_default: default = self.default() if callable(self.default) else self.default - desc += f' (Default: "{default}")' + if not desc.endswith('\n'): + desc += ' ' + desc += f'(Default: "{default}")' ret = '' ret = f'{self.name}\n' if wrap_text: @@ -146,11 +155,11 @@ def raw_value(self, name): description="""\ Whether to enable gathering runtime statistics on the `ocrd.profile` logger (comma-separated): - +\b - `CPU`: yields CPU and wall-time, - `RSS`: also yields peak memory (resident set size) - `PSS`: also yields peak memory (proportional set size) - +\b """, validator=lambda val : all(t in ('', 'CPU', 'RSS', 'PSS') for t in val.split(',')), default=(True, '')) @@ -183,11 +192,12 @@ def _ocrd_download_timeout_parser(val): config.add("OCRD_MISSING_INPUT", description="""\ -How to deal with missing input files (for some fileGrp/pageId) during processing: - +How to deal with missing input files +(for some fileGrp/pageId) during processing: +\b - `SKIP`: ignore and proceed with next page's input - `ABORT`: throw :py:class:`.MissingInputFile` - +\b """, default=(True, 'SKIP'), validator=lambda val: val in ['SKIP', 'ABORT'], @@ -195,12 +205,13 @@ def _ocrd_download_timeout_parser(val): config.add("OCRD_MISSING_OUTPUT", description="""\ -How to deal with missing output files (for some fileGrp/pageId) during processing: - +How to deal with missing output files +(for some fileGrp/pageId) during processing: +\b - `SKIP`: ignore and proceed processing next page - `COPY`: fall back to copying input PAGE to output fileGrp for page - `ABORT`: re-throw whatever caused processing to fail - +\b """, default=(True, 'SKIP'), validator=lambda val: val in ['SKIP', 'COPY', 'ABORT'], @@ -213,12 +224,13 @@ def _ocrd_download_timeout_parser(val): config.add("OCRD_EXISTING_OUTPUT", description="""\ -How to deal with already existing output files (for some fileGrp/pageId) during processing: - +How to deal with already existing output files +(for some fileGrp/pageId) during processing: +\b - `SKIP`: ignore and proceed processing next page - `OVERWRITE`: force writing result to output fileGrp for page - `ABORT`: re-throw :py:class:`FileExistsError` - +\b """, default=(True, 'SKIP'), validator=lambda val: val in ['SKIP', 'OVERWRITE', 'ABORT'],