From d8942646c5c34280538d7ec69e921c14b6d10fa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Mond=C3=A9jar=20Rubio?= Date: Sat, 10 Jul 2021 19:46:05 +0200 Subject: [PATCH] Add option to md2po for events targets displaying in extraction process --- .bumpversion.cfg | 2 +- mdpo/__init__.py | 2 +- mdpo/event.py | 78 +++++++++++++++++++++++++++++++ mdpo/md2po/__init__.py | 11 ++++- mdpo/md2po/__main__.py | 6 +++ setup.cfg | 2 +- test/test_md2po/test_md2po_cli.py | 33 ++++++++++++- 7 files changed, 129 insertions(+), 5 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 43f5050f..8614e264 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.3.57 +current_version = 0.3.58 [bumpversion:file:mdpo/__init__.py] diff --git a/mdpo/__init__.py b/mdpo/__init__.py index 651c61b8..04a16236 100644 --- a/mdpo/__init__.py +++ b/mdpo/__init__.py @@ -5,7 +5,7 @@ from mdpo.po2md import pofile_to_markdown -__version__ = '0.3.57' +__version__ = '0.3.58' __title__ = 'mdpo' __description__ = ('Markdown file translation utilities using PO files') __all__ = ( diff --git a/mdpo/event.py b/mdpo/event.py index c5d8aa5a..4c766928 100644 --- a/mdpo/event.py +++ b/mdpo/event.py @@ -1,5 +1,8 @@ """Custom events executed during the parsing process of an implementation.""" +import datetime +import sys + def raise_skip_event(events, event_name, *event_args): """Execute all functions defined for an event of a parser. @@ -25,3 +28,78 @@ def raise_skip_event(events, event_name, *event_args): if event(*event_args) is False: skip = True return skip + + +def _block_msg(block, details): + if details: + return f'{block.name} - {details}' + return block.name + + +def debug_events(program): + """Debugging events for interfaces. Displays in STDOUT all event targets. + + Args: + program (str): Command line interface name, to display it at the + beginning of the output. + + Returns: + dict: Event target printing functions. + """ + def debug(event, msg): + date = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + sys.stdout.write(f'{program}[DEBUG]::{date}::{event}:: {msg}\n') + + def print_msgid(self, msgid, msgstr, msgctxt, tcomment, flags): + msg = f'msgid=\'{msgid}\'' + if msgstr: + msg += f' - msgstr=\'{msgstr}\'' + if msgctxt: + msg += f' - msgctxt=\'{msgctxt}\'' + if tcomment: + msg += f' - tcomment=\'{tcomment}\'' + if flags: + msg += f' - flags=\'{flags}\'' + debug('msgid', msg) + + def print_command(self, mdpo_command, comment, original_command): + msg = mdpo_command + if comment: + msg += f' - {comment}' + if original_command and original_command != mdpo_command: + msg += f' (original command: \'{original_command}\')' + debug('command', msg) + + def print_enter_block(self, block, details): + debug('enter_block', _block_msg(block, details)) + + def print_leave_block(self, block, details): + debug('leave_block', _block_msg(block, details)) + + def print_enter_span(self, span, details): + debug('enter_span', _block_msg(span, details)) + + def print_leave_span(self, span, details): + debug('leave_span', _block_msg(span, details)) + + def print_text(self, block, text): + debug('text', text) + + def print_link_reference(self, target, href, title): + msg = f'target=\'{target}\'' + if href: + msg += f' - href=\'{href}\'' + if title: + msg += f' - title=\'{title}\'' + debug('link_reference', msg) + + return { + 'msgid': print_msgid, + 'command': print_command, + 'enter_block': print_enter_block, + 'leave_block': print_leave_block, + 'enter_span': print_enter_span, + 'leave_span': print_leave_span, + 'text': print_text, + 'link_reference': print_link_reference, + } diff --git a/mdpo/md2po/__init__.py b/mdpo/md2po/__init__.py index 56bc3a8d..0676d911 100644 --- a/mdpo/md2po/__init__.py +++ b/mdpo/md2po/__init__.py @@ -9,7 +9,7 @@ normalize_mdpo_command_aliases, parse_mdpo_html_command, ) -from mdpo.event import raise_skip_event +from mdpo.event import debug_events, raise_skip_event from mdpo.io import filter_paths, to_glob_or_content from mdpo.md import parse_link_references from mdpo.md4c import ( @@ -151,6 +151,11 @@ def __init__(self, glob_or_content, **kwargs): self.events[event_name] = ( [functions] if callable(functions) else functions ) + if kwargs.get('debug'): + for event_name, function in debug_events('md2po').items(): + if event_name not in self.events: + self.events[event_name] = [] + self.events[event_name].append(function) self.plaintext = kwargs.get('plaintext', False) @@ -935,6 +940,7 @@ def markdown_to_pofile( command_aliases={}, metadata={}, events={}, + debug=False, **kwargs, ): """Extracts all the msgids from a string of Markdown content or a group of @@ -1034,6 +1040,8 @@ def markdown_to_pofile( def msgid_event(self, msgid, *args): if msgid == 'foo': self._disable_next_line = True + debug (bool): Add events displaying all parsed elements in the + extraction process. Examples: >>> content = 'Some text with `inline code`' @@ -1069,6 +1077,7 @@ def msgid_event(self, msgid, *args): command_aliases=command_aliases, metadata=metadata, events=events, + debug=debug, **kwargs, ).extract( po_filepath=po_filepath, diff --git a/mdpo/md2po/__main__.py b/mdpo/md2po/__main__.py index 248f6ce5..1358b117 100755 --- a/mdpo/md2po/__main__.py +++ b/mdpo/md2po/__main__.py @@ -146,6 +146,11 @@ def build_parser(): ' \'-d "Content-Type: text/plain; charset=utf-8"' ' -d "Language: es"\'.', ) + parser.add_argument( + '-D', '--debug', dest='debug', action='store_true', + help='Print useful messages in the parsing process showing the' + ' contents of all Markdown elements.', + ) add_common_cli_latest_arguments(parser) return parser @@ -207,6 +212,7 @@ def run(args=[]): ignore_msgids=opts.ignore_msgids, command_aliases=opts.command_aliases, metadata=opts.metadata, + debug=opts.debug, ) if isinstance(opts.wrapwidth, int): kwargs['wrapwidth'] = opts.wrapwidth diff --git a/setup.cfg b/setup.cfg index 5e4a8e59..bd952942 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = mdpo -version = 0.3.57 +version = 0.3.58 description = Markdown files translation using PO files. long_description = file: README.md long_description_content_type = text/markdown diff --git a/test/test_md2po/test_md2po_cli.py b/test/test_md2po/test_md2po_cli.py index c4152eeb..016dcf6f 100644 --- a/test/test_md2po/test_md2po_cli.py +++ b/test/test_md2po/test_md2po_cli.py @@ -1,5 +1,8 @@ +"""Tests for md2po command line interface.""" + import io import os +import re import subprocess import sys import tempfile @@ -33,7 +36,7 @@ def test_stdin(striplastline, capsys, monkeypatch): assert striplastline(out) == EXAMPLE['output'] -def test_stdin_no_atty(striplastline, tmp_file): +def test_stdin_subprocess_input(striplastline, tmp_file): proc = subprocess.run( 'md2po', universal_newlines=True, @@ -81,6 +84,34 @@ def test_quiet(capsys, arg): assert out == '' +@pytest.mark.parametrize('arg', ['-D', '--debug']) +def test_debug(capsys, arg): + pofile, exitcode = run([EXAMPLE['input'], arg]) + out, err = capsys.readouterr() + + assert exitcode == 0 + assert pofile.__unicode__() == EXAMPLE['output'] + + po_output_checked = False + + outlines = out.splitlines() + for i, line in enumerate(outlines): + assert re.match( + ( + r'^md2po\[DEBUG\]::\d{4,}-\d\d-\d\d\s\d\d:\d\d:\d\d::' + r'(text|link_reference|msgid|command|enter_block|' + r'leave_block|enter_span|leave_span)::' + ), + line, + ) + if line.endswith('msgid=\'\''): + assert '\n'.join(outlines[i + 1:]) == EXAMPLE['output'] + po_output_checked = True + break + + assert po_output_checked + + @pytest.mark.parametrize('arg', ['-po', '--po-filepath', '--pofilepath']) def test_po_filepath(striplastline, capsys, arg, tmp_file): pofile_content = '''#