From 34af71eae91babad2359efb9334b7a3c4dc55159 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Mond=C3=A9jar?= Date: Sun, 7 Nov 2021 14:17:22 +0100 Subject: [PATCH] Modernize codebase, unify variable names... (#172) * Refactor * Get rid of `striplastline` tests fixture * Rewrite `tempfile.NamedTemporaryFile` in tests using context manager * Remove uneeded casts to str in tests * Refactor `capsys.readouterr` calls in tests * Drop uneeded cast to str * Refactor print comments * Drop uneeded casts to `str` comparing `polib.POFile` with strings * Improve test * Add more tests and refactor function * Allow to pass negative values to `wrapwidth` arguments. * Rewrite incorrect statement from docs * Remove some 'pragma: no cover' comments * Drop `filehash` and `save_pofile_checking_file_changed` functions * Fix empty indented code block line error in `po2md` * Bump version * Fix image links regression from v0.3.68 --- .bumpversion.cfg | 2 +- .pre-commit-config.yaml | 1 + docs/pre-commit-hooks.rst | 10 +- mdpo/__init__.py | 2 +- mdpo/event.py | 2 +- mdpo/html.py | 4 +- mdpo/io.py | 24 +- mdpo/md.py | 15 +- mdpo/md2po/__init__.py | 50 ++-- mdpo/md2po/__main__.py | 11 +- mdpo/md2po2md/__init__.py | 14 +- mdpo/md2po2md/__main__.py | 4 +- mdpo/mdpo2html/__init__.py | 65 +++--- mdpo/mdpo2html/__main__.py | 2 +- mdpo/po.py | 26 +-- mdpo/po2md/__init__.py | 51 +++-- mdpo/po2md/__main__.py | 10 +- mdpo/text.py | 16 +- setup.cfg | 2 +- test/conftest.py | 27 +-- test/test_cli.py | 10 +- .../extract-examples/markuptext/images.md | 6 + .../markuptext/images.md.expect.po | 14 ++ .../test_commands/test_md2po_codeblocks.py | 10 +- .../test_commands/test_md2po_context.py | 2 +- .../test_commands/test_md2po_disable.py | 8 +- .../test_commands/test_md2po_include.py | 6 +- .../test_commands/test_md2po_translator.py | 2 +- test/test_md2po/test_extract.py | 36 ++- test/test_md2po/test_extractor.py | 32 ++- test/test_md2po/test_md2po_cli.py | 214 +++++++++--------- test/test_md2po/test_md2po_events.py | 63 +++++- test/test_md2po/test_obsoletes.py | 77 ++++--- test/test_md2po/test_x_headers.py | 4 +- test/test_mdpo2html/test_mdpo2html_cli.py | 64 +++--- test/test_po2md/test_po2md_cli.py | 55 +++-- test/test_po2md/test_po2md_translate.py | 10 +- .../translate-examples/code-blocks.md | 2 + .../code-blocks.md.expect.md | 2 + test/test_po2md/translate-examples/images.md | 8 +- .../translate-examples/images.md.expect.md | 7 + test/test_po2md/translate-examples/images.po | 12 + test/test_text.py | 56 ++++- 43 files changed, 593 insertions(+), 445 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 4b4e6969..b41be539 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.3.70 +current_version = 0.3.71 [bumpversion:file:mdpo/__init__.py] diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 49a47e62..24fd05f2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -10,6 +10,7 @@ repos: hooks: - id: trailing-whitespace name: trailing-whitespace + exclude: test/test_po2md/translate-examples/code-blocks.* - id: end-of-file-fixer name: end-of-file-fixer - id: double-quote-string-fixer diff --git a/docs/pre-commit-hooks.rst b/docs/pre-commit-hooks.rst index eeec67d9..0fcf2407 100644 --- a/docs/pre-commit-hooks.rst +++ b/docs/pre-commit-hooks.rst @@ -15,7 +15,7 @@ so you don't need to specify them. .. code-block:: yaml - repo: https://github.com/mondeja/mdpo - rev: v0.3.70 + rev: v0.3.71 hooks: - id: md2po args: @@ -43,7 +43,7 @@ po2md .. code-block:: yaml - repo: https://github.com/mondeja/mdpo - rev: v0.3.70 + rev: v0.3.71 hooks: - id: po2md args: @@ -56,7 +56,7 @@ po2md .. code-block:: yaml - repo: https://github.com/mondeja/mdpo - rev: v0.3.70 + rev: v0.3.71 hooks: - id: po2md files: README\.md @@ -75,7 +75,7 @@ md2po2md .. code-block:: yaml - repo: https://github.com/mondeja/mdpo - rev: v0.3.70 + rev: v0.3.71 hooks: - id: md2po2md args: @@ -88,7 +88,7 @@ md2po2md .. code-block:: yaml - repo: https://github.com/mondeja/mdpo - rev: v0.3.70 + rev: v0.3.71 hooks: - id: md2po2md files: README\.md diff --git a/mdpo/__init__.py b/mdpo/__init__.py index a14bce83..71f3d57a 100644 --- a/mdpo/__init__.py +++ b/mdpo/__init__.py @@ -6,7 +6,7 @@ from mdpo.po2md import pofile_to_markdown -__version__ = '0.3.70' +__version__ = '0.3.71' __title__ = 'mdpo' __description__ = ('Markdown files translation using PO files.') __all__ = ( diff --git a/mdpo/event.py b/mdpo/event.py index 7140560b..b22d9d10 100644 --- a/mdpo/event.py +++ b/mdpo/event.py @@ -36,7 +36,7 @@ def _block_msg(block, details): return block.name -def debug_events(program): # pragma: no cover +def debug_events(program): """Debugging events for interfaces. Displays in STDOUT all event targets. Args: diff --git a/mdpo/html.py b/mdpo/html.py index 5027f2f9..8de609c0 100644 --- a/mdpo/html.py +++ b/mdpo/html.py @@ -18,9 +18,9 @@ def html_attrs_tuple_to_string(attrs): """ response = '' for i, (name, value) in enumerate(attrs): - response += '%s' % name + response += name if value is not None: - response += '="%s"' % value + response += f'="{value}"' if i < len(attrs) - 1: response += ' ' return response diff --git a/mdpo/io.py b/mdpo/io.py index 4a2ea5c5..6a90158f 100644 --- a/mdpo/io.py +++ b/mdpo/io.py @@ -1,9 +1,13 @@ """mdpo I/O utilities.""" +import filecmp import glob -import hashlib import os import re +import tempfile + + +MDPO_FILECMP_TEMPFILE = os.path.join(tempfile.gettempdir(), '__mpdo-filecmp') def filter_paths(filepaths, ignore_paths=[]): @@ -85,18 +89,6 @@ def to_glob_or_content(value): return (True, parsed) -def filehash(filepath): - """Compute the hash of a file. - - Args: - filepath (str): Path to the file. - """ - hasher = hashlib.md5() - with open(filepath, 'rb') as f: - hasher.update(f.read()) - return hasher.hexdigest() - - def save_file_checking_file_changed(filepath, content, encoding='utf-8'): """Save a file checking if the content has changed. @@ -112,9 +104,9 @@ def save_file_checking_file_changed(filepath, content, encoding='utf-8'): f.write(content) return True - pre_hash = filehash(filepath) + with open(MDPO_FILECMP_TEMPFILE, 'w') as temp_f, open(filepath) as f: + temp_f.write(f.read()) with open(filepath, 'w', encoding=encoding) as f: f.write(content) - post_hash = filehash(filepath) - return pre_hash != post_hash + return filecmp.cmp(MDPO_FILECMP_TEMPFILE, filepath) diff --git a/mdpo/md.py b/mdpo/md.py index 93aede7c..9a3fe5da 100644 --- a/mdpo/md.py +++ b/mdpo/md.py @@ -46,9 +46,8 @@ def escape_links_titles(text, link_start_string='[', link_end_string=']'): for match in re.findall(regex, text): original_string = match[0] + match[1] - target_string = match[0] + '"%s"' % ( - match[1][1:-1].replace('"', '\\"') - ) + escaped_title = match[1][1:-1].replace('"', '\\"') + target_string = f'{match[0]}"{escaped_title}"' text = text.replace(original_string, target_string) return text @@ -418,10 +417,10 @@ def solve_link_reference_targets(translations): # store in solutions solutions[new_msgid] = new_msgstr - # print("----> new_msgid", new_msgid) - # print("----> new_msgstr", new_msgstr) + # print('----> new_msgid', new_msgid) + # print('----> new_msgstr', new_msgstr) - # print("----> link_references_text_targets", link_references_text_targets) - # print("----> msgid_msgstrs_with_links", msgid_msgstrs_with_links) - # print("----> solutions", solutions) + # print('----> link_references_text_targets', link_references_text_targets) + # print('----> msgid_msgstrs_with_links', msgid_msgstrs_with_links) + # print('----> solutions', solutions) return solutions diff --git a/mdpo/md2po/__init__.py b/mdpo/md2po/__init__.py index efadba9a..b8031584 100644 --- a/mdpo/md2po/__init__.py +++ b/mdpo/md2po/__init__.py @@ -10,7 +10,11 @@ parse_mdpo_html_command, ) from mdpo.event import debug_events, raise_skip_event -from mdpo.io import filter_paths, to_glob_or_content +from mdpo.io import ( + filter_paths, + save_file_checking_file_changed, + to_glob_or_content, +) from mdpo.md import parse_link_references from mdpo.md4c import ( DEFAULT_MD4C_GENERIC_PARSER_EXTENSIONS, @@ -21,7 +25,6 @@ mark_not_found_entries_as_obsoletes, po_escaped_string, remove_not_found_entries, - save_pofile_checking_file_changed, ) from mdpo.text import min_not_max_chars_in_a_row, parse_wrapwidth_argument @@ -172,7 +175,7 @@ def __init__(self, glob_or_content, **kwargs): self._include_next_codeblock = False self._disable_next_codeblock = False - self._saved_files_changed = ( # pragma: no cover + self._saved_files_changed = ( False if kwargs.get('_check_saved_files_changed') else None ) @@ -781,16 +784,30 @@ def leave_span(self, span, details): ) self._codespan_backticks = None elif span is md4c.SpanType.IMG: - self._current_msgid += '![{}]({}'.format( - self._current_imgspan['text'], - self._current_imgspan['src'], - ) - if self._current_imgspan['title']: - self._current_msgid += ' "%s"' % ( - self._current_imgspan['title'] + # TODO: refactor with getattr? Currently getting next error + # getattr(self, target_varname) += '![{}]({}'.format( + # SyntaxError: cannot assign to function call + + if not self._inside_aspan: + self._current_msgid += '![{}]({}'.format( + self._current_imgspan['text'], + self._current_imgspan['src'], + ) + title = self._current_imgspan['title'] + if title: + self._current_msgid += f' "{title}"' + self._current_msgid += ')' + self._current_imgspan = {} + else: + self._current_aspan_text += '![{}]({}'.format( + self._current_imgspan['text'], + self._current_imgspan['src'], ) - self._current_msgid += ')' - self._current_imgspan = {} + title = self._current_imgspan['title'] + if title: + self._current_aspan_text += f' "{title}"' + self._current_aspan_text += ')' + self._current_imgspan = {} elif span is md4c.SpanType.U: self._inside_uspan = False @@ -968,9 +985,10 @@ def _parse(content): if save and po_filepath: if self._saved_files_changed is False: # pragma: no cover - self._saved_files_changed = save_pofile_checking_file_changed( - self.pofile, + self._saved_files_changed = save_file_checking_file_changed( po_filepath, + str(self.pofile), + encoding=self.pofile.encoding, ) else: self.pofile.save(fpath=po_filepath) @@ -1034,8 +1052,8 @@ def markdown_to_pofile( for you. It depends on the use you are going to give to this library activate this mode (``plaintext=False``) or not. wrapwidth (int): Wrap width for po file indicated at ``po_filepath`` - parameter. Only useful when the ``-w`` option was passed - to xgettext. + parameter. If negative, 0, 'inf' or 'math.inf' the content won't + be wrapped. mark_not_found_as_obsolete (bool): The strings extracted from markdown that will not be found inside the provided pofile will be marked as obsolete. diff --git a/mdpo/md2po/__main__.py b/mdpo/md2po/__main__.py index c5ea89e4..f0453a26 100755 --- a/mdpo/md2po/__main__.py +++ b/mdpo/md2po/__main__.py @@ -76,9 +76,8 @@ def build_parser(): '-w', '--wrapwidth', dest='wrapwidth', metavar='N/inf', type=str, default='78', help='Wrap width for po file indicated at \'-po/--po-filepath\'' - ' parameter. Only useful when the \'-w\' option was passed to' - ' xgettext. You can use the values \'0\' and \'inf\' for infinite' - ' width.', + ' parameter. If negative, \'0\' or \'inf\', the PO file content' + ' will not be wrapped.', ) parser.add_argument( '-m', '--merge-po-files', '--merge-pofiles', @@ -204,12 +203,10 @@ def run(args=[]): pofile = md2po.extract(**extract_kwargs) if not opts.quiet: - sys.stdout.write(pofile.__unicode__() + '\n') + sys.stdout.write(f'{pofile}\n') # pre-commit mode - if ( # pragma: no cover - opts.check_saved_files_changed and md2po._saved_files_changed - ): + if opts.check_saved_files_changed and md2po._saved_files_changed: return (pofile, 1) return (pofile, 0) diff --git a/mdpo/md2po2md/__init__.py b/mdpo/md2po2md/__init__.py index b8c1213b..5af777de 100644 --- a/mdpo/md2po2md/__init__.py +++ b/mdpo/md2po2md/__init__.py @@ -108,9 +108,9 @@ def markdown_to_pofile_to_markdown( os.makedirs(os.path.abspath(po_dirpath), exist_ok=True) if os.path.isdir(po_filepath): - po_filepath = ( - po_filepath.rstrip(os.sep) + os.sep + - os.path.basename(filepath) + '.po' + po_filepath = os.path.join( + po_filepath.rstrip(os.sep), + f'{os.path.basename(filepath)}.po', ) if not po_filepath.endswith('.po'): po_filepath += '.po' @@ -139,9 +139,7 @@ def markdown_to_pofile_to_markdown( po_encoding=po_encoding, md_encoding=md_encoding, ) - if ( # pragma: no cover - _check_saved_files_changed and _saved_files_changed is False - ): + if _check_saved_files_changed and _saved_files_changed is False: _saved_files_changed = md2po._saved_files_changed # po2md @@ -158,9 +156,7 @@ def markdown_to_pofile_to_markdown( save=md_filepath, md_encoding=md_encoding, ) - if ( # pragma: no cover - _check_saved_files_changed and _saved_files_changed is False - ): + if _check_saved_files_changed and _saved_files_changed is False: _saved_files_changed = po2md._saved_files_changed return _saved_files_changed diff --git a/mdpo/md2po2md/__main__.py b/mdpo/md2po2md/__main__.py index 6619282d..f2538457 100644 --- a/mdpo/md2po2md/__main__.py +++ b/mdpo/md2po2md/__main__.py @@ -112,9 +112,7 @@ def run(args=[]): _check_saved_files_changed=opts.check_saved_files_changed, **kwargs, ) - if ( # pragma: no cover - opts.check_saved_files_changed and _saved_files_changed - ): + if opts.check_saved_files_changed and _saved_files_changed: exitcode = 1 return exitcode diff --git a/mdpo/mdpo2html/__init__.py b/mdpo/mdpo2html/__init__.py index 81abbcb7..74acecc9 100644 --- a/mdpo/mdpo2html/__init__.py +++ b/mdpo/mdpo2html/__init__.py @@ -123,7 +123,7 @@ def _remove_lastline_from_output_if_empty(self): self.output = '\n'.join(split_output)[:-1] def _process_replacer(self): - # print("REPLACER:", self.replacer) + # print('REPLACER:', self.replacer) template_tags = [] raw_html_template, _current_replacement = ('', '') @@ -143,7 +143,7 @@ def _process_replacer(self): raw_html_template += '<{}{}>'.format( handled, ( - ' ' + html_attrs_tuple_to_string(attrs) + f' {html_attrs_tuple_to_string(attrs)}' if attrs else '' ), ) @@ -152,7 +152,7 @@ def _process_replacer(self): raw_html_template += '<{}{}>'.format( handled, ( - ' ' + html_attrs_tuple_to_string(attrs) + f' {html_attrs_tuple_to_string(attrs)}' if attrs else '' ), ) @@ -161,25 +161,24 @@ def _process_replacer(self): raw_html_template += '<{}{}>'.format( handled, ( - ' ' + html_attrs_tuple_to_string(attrs) + f' {html_attrs_tuple_to_string(attrs)}' if attrs else '' ), ) elif handled in self.link_tags: title = get_html_attrs_tuple_attr(attrs, 'title') - _current_link_target += '(%s' % get_html_attrs_tuple_attr( - attrs, 'href', - ) + href = get_html_attrs_tuple_attr(attrs, 'href') + _current_link_target += f'({href}' if title: - _current_link_target += ' "%s"' % title + _current_link_target += f' "{title}"' _current_link_target += ')' - raw_html_template += '<%s' % handled + raw_html_template += f'<{handled}' # attrs_except_href_title = [] for attr, value in attrs: if attr in ['title', 'href']: - raw_html_template += ' %s="{}"' % attr + raw_html_template += f' {attr}="{{}}"' # else: # These attributes are not included in output # attrs_except_href_title.append((attr, value)) @@ -191,7 +190,7 @@ def _process_replacer(self): else: raw_html_template += '<{}{}>'.format( handled, - ' ' + html_attrs_tuple_to_string(attrs) + f' {html_attrs_tuple_to_string(attrs)}' if attrs else '', ) _last_start_tag = handled @@ -215,7 +214,7 @@ def _process_replacer(self): else: _current_replacement += handled elif handle == 'end': - raw_html_template += '' % handled + raw_html_template += f'' if handled in self.code_tags: _current_replacement += '`' elif handled in self.bold_tags: @@ -226,7 +225,7 @@ def _process_replacer(self): if _last_end_tag == 'code': _inside_code = False elif handle == 'comment': - raw_html_template += '' % handled + raw_html_template += f'' elif handle == 'startend': if handled in self.image_tags: _current_replacement += '![{}]({}'.format( @@ -235,7 +234,7 @@ def _process_replacer(self): ) title = get_html_attrs_tuple_attr(attrs, 'title') if title: - _current_replacement += ' "%s"' % title + _current_replacement += f' "{title}"' _current_replacement += ')' raw_html_template += '{}' @@ -243,7 +242,7 @@ def _process_replacer(self): raw_html_template += '<{}{}/>'.format( handled, ( - (' %s' % html_attrs_tuple_to_string(attrs)) + f' {html_attrs_tuple_to_string(attrs)}' if attrs else '' ), ) @@ -278,9 +277,9 @@ def _process_replacer(self): if tag not in template_tags: template_tags.append(tag) - # print("RAW TEMPLATE:", raw_html_template) - # print("TEMPLATE TAGS:", template_tags) - # print('CURRENT MSGID: \'%s\'' % _current_replacement) + # print('RAW TEMPLATE:', raw_html_template) + # print('TEMPLATE TAGS:', template_tags) + # print(f'CURRENT MSGID: \'{_current_replacement}\'') # print('MSGSTR:', replacement) html_before_first_replacement = raw_html_template.split('{')[0] @@ -288,9 +287,9 @@ def _process_replacer(self): for tags_group in [self.bold_tags, self.italic_tags, self.code_tags]: for tag in tags_group: html_before_first_replacement = \ - html_before_first_replacement.split('<%s>' % tag)[0] + html_before_first_replacement.split(f'<{tag}>')[0] html_after_last_replacement = \ - html_after_last_replacement.split('' % tag)[-1] + html_after_last_replacement.split(f'')[-1] html_before_first_replacement = \ html_before_first_replacement.split('' if self.context: self.context.pop() elif self.context and self.context[0] in self.ignore_grouper_tags: - self.output += '' % tag + self.output += f'' elif tag in PROCESS_REPLACER_TAGS: self.replacer.append(('end', tag, None)) self._process_replacer() elif tag in ['ul', 'blockquote', 'tr', 'table', 'thead', 'tbody']: - self.output += '' % tag + self.output += f'' else: self.replacer.append(('end', tag, None)) if self.context: self.context.pop() def handle_startendtag(self, tag, attrs): - # print("STARTEND TAG: %s | POS: %d:%d" % (tag, *self.getpos())) + # print('STARTEND TAG: %s | POS: %d:%d' % (tag, *self.getpos())) if not self.replacer: self.output += self.get_starttag_text() @@ -378,7 +377,7 @@ def handle_startendtag(self, tag, attrs): self.replacer.append(('startend', tag, attrs)) def handle_data(self, data): - # print(" DATA: '%s'" % (data)) + # print(f' DATA: \'{data}\'') if data: if not self.replacer or ( @@ -394,7 +393,7 @@ def handle_data(self, data): self.replacer.append(('data', data, None)) def handle_comment(self, data): - # print(" COMMENT: '%s'" % (data)) + # print(f' COMMENT: \'{data}\'') if self.replacer: self.replacer.append(('comment', data, None)) diff --git a/mdpo/mdpo2html/__main__.py b/mdpo/mdpo2html/__main__.py index 33bbf3c7..84f57ae5 100644 --- a/mdpo/mdpo2html/__main__.py +++ b/mdpo/mdpo2html/__main__.py @@ -103,7 +103,7 @@ def run(args=[]): ) if not opts.quiet and not opts.save: - sys.stdout.write(output + '\n') + sys.stdout.write(f'{output}\n') return (output, 0) diff --git a/mdpo/po.py b/mdpo/po.py index 4780a1fe..11022854 100644 --- a/mdpo/po.py +++ b/mdpo/po.py @@ -1,11 +1,10 @@ """``.po`` files related stuff.""" import glob -import os import polib -from mdpo.io import filehash, filter_paths +from mdpo.io import filter_paths from mdpo.polib import poentry__cmp__ @@ -21,7 +20,7 @@ def po_escaped_string(chars): Returns: str: First character of passed string with ``\`` character prepended. """ - return '\\' + chars[0] + return f'\\{chars[0]}' def find_entry_in_entries(entry, entries, **kwargs): @@ -162,24 +161,3 @@ def paths_or_globs_to_unique_pofiles(pofiles_globs, ignore, po_encoding=None): _po_filepaths.append(po_filepath) return pofiles - - -def save_pofile_checking_file_changed(pofile, po_filepath): - """Save a :py:class:`polib.POFile` checking if the content has changed. - - Args: - pofile (:py:class:`polib.POFile`): POFile to save. - po_filepath (str): Path to the new file to save in. - - Returns: - bool: If the PO file content has been changed. - """ - if not os.path.isfile(po_filepath): - pofile.save(fpath=po_filepath) - return True - - pre_hash = filehash(po_filepath) - pofile.save(fpath=po_filepath) - post_hash = filehash(po_filepath) - - return pre_hash != post_hash diff --git a/mdpo/po2md/__init__.py b/mdpo/po2md/__init__.py index ba761cf2..16ee9d14 100644 --- a/mdpo/po2md/__init__.py +++ b/mdpo/po2md/__init__.py @@ -153,7 +153,7 @@ def __init__(self, pofiles, ignore=[], po_encoding=None, **kwargs): ) if 'wrapwidth' in kwargs else 80 ) - self._saved_files_changed = ( # pragma: no cover + self._saved_files_changed = ( False if kwargs.get('_check_saved_files_changed') else None ) @@ -360,8 +360,6 @@ def _save_current_msgid(self): if self._inside_indented_codeblock: new_translation = '' for line in translation.splitlines(): - if not line: - continue new_translation += f' {line}\n' translation = new_translation else: @@ -421,7 +419,7 @@ def _save_current_line(self): def enter_block(self, block, details): # raise 'enter_block' event - if raise_skip_event( # pragma: no cover + if raise_skip_event( self.events, 'enter_block', self, block, @@ -459,7 +457,8 @@ def enter_block(self, block, details): self._save_current_line() elif block is md4c.BlockType.H: self._inside_hblock = True - self._current_line += '%s ' % ('#' * details['level']) + hash_signs = '#' * details['level'] + self._current_line += f'{hash_signs} ' elif block is md4c.BlockType.LI: if self._current_list_type[-1][0] == 'ol': # inside OL @@ -480,7 +479,8 @@ def enter_block(self, block, details): self._ul_marks[-1], ) if details['is_task']: - self._current_line += '[%s] ' % details['task_mark'] + mark = details['task_mark'] + self._current_line += f'[{mark}] ' self._current_list_type[-1][-1].append(details['is_task']) self._inside_liblock = True self._inside_liblock_first_p = True @@ -528,7 +528,7 @@ def enter_block(self, block, details): def leave_block(self, block, details): # raise 'leave_block' event - if raise_skip_event( # pragma: no cover + if raise_skip_event( self.events, 'leave_block', self, @@ -671,7 +671,7 @@ def leave_block(self, block, details): def enter_span(self, span, details): # raise 'enter_span' event - if raise_skip_event( # pragma: no cover + if raise_skip_event( self.events, 'enter_span', self, @@ -731,7 +731,7 @@ def enter_span(self, span, details): def leave_span(self, span, details): # raise 'leave_span' event - if raise_skip_event( # pragma: no cover + if raise_skip_event( self.events, 'leave_span', self, @@ -794,20 +794,33 @@ def leave_span(self, span, details): ) self._codespan_backticks = None elif span is md4c.SpanType.IMG: - self._current_msgid += '![{}]({}'.format( - self._current_imgspan['text'], - self._current_imgspan['src'], - ) - if self._current_imgspan['title']: - self._current_msgid += ' "%s"' % polib.escape( - self._current_imgspan['title'], + # TODO: refactor with getattr? Currently getting next error + # getattr(self, target_varname) += '![{}]({}'.format( + # SyntaxError: cannot assign to function call + + if not self._inside_aspan: + self._current_msgid += '![{}]({}'.format( + self._current_imgspan['text'], + self._current_imgspan['src'], + ) + if self._current_imgspan['title']: + title = self._current_imgspan['title'] + self._current_msgid += f' "{title}"' + self._current_msgid += ')' + else: + self._current_aspan_text += '![{}]({}'.format( + self._current_imgspan['text'], + self._current_imgspan['src'], ) - self._current_msgid += ')' + if self._current_imgspan['title']: + title = self._current_imgspan['title'] + self._current_aspan_text += f' "{title}"' + self._current_aspan_text += ')' self._current_imgspan = {} def text(self, block, text): # raise 'text' event - if raise_skip_event( # pragma: no cover + if raise_skip_event( self.events, 'text', self, @@ -939,7 +952,7 @@ def translate( self.output = '\n'.join(self._outputlines) if save: - if self._saved_files_changed is False: # pragma: no cover + if self._saved_files_changed is False: self._saved_files_changed = save_file_checking_file_changed( save, self.output, diff --git a/mdpo/po2md/__main__.py b/mdpo/po2md/__main__.py index 3dd2e4c4..cf0d4de0 100644 --- a/mdpo/po2md/__main__.py +++ b/mdpo/po2md/__main__.py @@ -59,8 +59,8 @@ def build_parser(): ) parser.add_argument( '-w', '--wrapwidth', dest='wrapwidth', default='80', type=str, - help='Maximum width rendering the Markdown output, when possible. You' - ' can use the values \'0\' and \'inf\' for infinite width.', + help='Maximum width rendering the Markdown output, when possible. If' + ' negative, \'0\' or \'inf\', the content will not be wrapped.', metavar='N/inf', ) add_encoding_arguments(parser) @@ -117,12 +117,10 @@ def run(args=[]): ) if not opts.quiet and not opts.save: - sys.stdout.write(output + '\n') + sys.stdout.write(f'{output}\n') # pre-commit mode - if ( # pragma: no cover - opts.check_saved_files_changed and po2md._saved_files_changed - ): + if opts.check_saved_files_changed and po2md._saved_files_changed: return (output, 1) return (output, 0) diff --git a/mdpo/text.py b/mdpo/text.py index 9caf1be3..f8e902ac 100644 --- a/mdpo/text.py +++ b/mdpo/text.py @@ -112,13 +112,11 @@ def parse_strint_0_inf(value): Args: value (str): Value to parse. """ + num = float(value) try: - num = int(value) - except ValueError: - if value.lower() == 'inf': - return math.inf - raise ValueError(value) - return num if num else math.inf + return int(num) if num > 0 else math.inf + except OverflowError: # cannot convert float infinity to integer + return math.inf def parse_wrapwidth_argument(value): @@ -130,7 +128,7 @@ def parse_wrapwidth_argument(value): try: value = parse_strint_0_inf(value) except ValueError as err: - if os.environ.get('_MDPO_RUNNING'): + if os.environ.get('_MDPO_RUNNING'): # executed as CLI sys.stderr.write( f"Invalid value '{err.value}' for -w/--wrapwidth argument.\n", ) @@ -160,7 +158,7 @@ def removeprefix(text, prefix): return text.removeprefix(prefix) if text.startswith(prefix): return text[len(prefix):] - return text # pragma: no cover + return text def removesuffix(text, suffix): @@ -183,4 +181,4 @@ def removesuffix(text, suffix): return text.removesuffix(suffix) if suffix and text.endswith(suffix): return text[:-len(suffix)] - return text # pragma: no cover + return text diff --git a/setup.cfg b/setup.cfg index 0973fc23..d07d43ae 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = mdpo -version = 0.3.70 +version = 0.3.71 description = Markdown files translation using PO files. long_description = file: README.md long_description_content_type = text/markdown diff --git a/test/conftest.py b/test/conftest.py index a42f675c..20a7ae0a 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -6,33 +6,12 @@ @contextmanager def _tmp_file(content, suffix): - f = tempfile.NamedTemporaryFile(suffix=suffix) - f.write(content.encode('utf-8')) - f.seek(0) - try: + with tempfile.NamedTemporaryFile(suffix=suffix) as f: + f.write(content.encode('utf-8')) + f.seek(0) yield f.name - finally: - f.close() @pytest.fixture() def tmp_file(): return _tmp_file - - -@pytest.fixture() -def striplastline(): - """Returns a text, ignoring the last line. - - Args: - text (str): Text that will be returned ignoring its last line. - - Returns: - str: Text wihout their last line. - """ - def _striplastline(text): - stripped_text = '\n'.join(text.split('\n')[:-1]) - if len(stripped_text) == len(text): - raise Exception('Unnecessary use of \'striplastline\' fixture') - return stripped_text - return _striplastline diff --git a/test/test_cli.py b/test/test_cli.py index d1f2ad5c..53377192 100644 --- a/test/test_cli.py +++ b/test/test_cli.py @@ -23,7 +23,8 @@ None, ( "The value 'foobar' passed to argument --command-alias" - " can't be parsed." + " can't be parsed. Please, separate the pair" + " '' with a ':' character.\n" ), id='foobar-error: unparsed alias resolution', ), @@ -32,7 +33,7 @@ None, ( "Multiple resolutions for 'foo' alias passed to" - ' --command-alias arguments.' + ' --command-alias arguments.\n' ), id='foo:bar,foo:baz-error: multiple resolutions for alias', ), @@ -47,8 +48,9 @@ def test_parse_command_aliases_cli_arguments( if expected_stderr: with pytest.raises(SystemExit): parse_command_aliases_cli_arguments(command_aliases) - out, err = capsys.readouterr() - assert expected_stderr in err + stdout, stderr = capsys.readouterr() + assert stderr == expected_stderr + assert stdout == '' else: assert parse_command_aliases_cli_arguments( command_aliases, diff --git a/test/test_md2po/extract-examples/markuptext/images.md b/test/test_md2po/extract-examples/markuptext/images.md index 49c85c11..a4f7f4ad 100644 --- a/test/test_md2po/extract-examples/markuptext/images.md +++ b/test/test_md2po/extract-examples/markuptext/images.md @@ -9,3 +9,9 @@ [id]: url/to/image "Optional title attribute" My ![foo bar](/path/to/train.jpg "title") + +[![Image inside inline link](https://image.ext)](https://link.ext) + +[![Image inside referenced link](https://image.ext)][1] + +[1]: https://link-1.ext diff --git a/test/test_md2po/extract-examples/markuptext/images.md.expect.po b/test/test_md2po/extract-examples/markuptext/images.md.expect.po index 5a20893e..bf0ecd57 100644 --- a/test/test_md2po/extract-examples/markuptext/images.md.expect.po +++ b/test/test_md2po/extract-examples/markuptext/images.md.expect.po @@ -16,3 +16,17 @@ msgstr "" msgid "My ![foo bar](/path/to/train.jpg \"title\")" msgstr "" + +msgid "[![Image inside inline link](https://image.ext)](https://link.ext)" +msgstr "" + +msgid "[![Image inside referenced link](https://image.ext)][1]" +msgstr "" + +#, fuzzy +msgid "[id]: url/to/image \"Optional title attribute\"" +msgstr "[id]: url/to/image \"Optional title attribute\"" + +#, fuzzy +msgid "[1]: https://link-1.ext" +msgstr "[1]: https://link-1.ext" diff --git a/test/test_md2po/test_commands/test_md2po_codeblocks.py b/test/test_md2po/test_commands/test_md2po_codeblocks.py index fbd49fbb..51335b8c 100644 --- a/test/test_md2po/test_commands/test_md2po_codeblocks.py +++ b/test/test_md2po/test_commands/test_md2po_codeblocks.py @@ -21,7 +21,7 @@ def test_include_indented_codeblock(command, command_aliases): var thisCodeMustNotBeIncluded = undefined; ''' pofile = markdown_to_pofile(content, command_aliases=command_aliases) - assert pofile.__unicode__() == '''# + assert pofile == '''# msgid "" msgstr "" @@ -50,7 +50,7 @@ def test_include_fenced_codeblock(): ``` ''' pofile = markdown_to_pofile(content) - assert pofile.__unicode__() == '''# + assert pofile == '''# msgid "" msgstr "" @@ -88,7 +88,7 @@ def test_disable_next_codeblock(command, command_aliases): command_aliases=command_aliases, include_codeblocks=True, ) - assert pofile.__unicode__() == '''# + assert pofile == '''# msgid "" msgstr "" @@ -125,7 +125,7 @@ def test_disable_codeblocks(command, command_aliases): command_aliases=command_aliases, include_codeblocks=True, ) - assert pofile.__unicode__() == '''# + assert pofile == '''# msgid "" msgstr "" @@ -164,7 +164,7 @@ def test_include_codeblocks(command, command_aliases): command_aliases=command_aliases, include_codeblocks=False, ) - assert pofile.__unicode__() == '''# + assert pofile == '''# msgid "" msgstr "" diff --git a/test/test_md2po/test_commands/test_md2po_context.py b/test/test_md2po/test_commands/test_md2po_context.py index a58f9e28..e0abca78 100644 --- a/test/test_md2po/test_commands/test_md2po_context.py +++ b/test/test_md2po/test_commands/test_md2po_context.py @@ -17,7 +17,7 @@ def test_context(command, command_aliases): May ''' pofile = markdown_to_pofile(content, command_aliases=command_aliases) - assert pofile.__unicode__() == '''# + assert pofile == '''# msgid "" msgstr "" diff --git a/test/test_md2po/test_commands/test_md2po_disable.py b/test/test_md2po/test_commands/test_md2po_disable.py index 4f068868..175fca2f 100644 --- a/test/test_md2po/test_commands/test_md2po_disable.py +++ b/test/test_md2po/test_commands/test_md2po_disable.py @@ -28,7 +28,7 @@ def test_disable_enable(commands, command_aliases): This must be included also. ''' pofile = markdown_to_pofile(content, command_aliases=command_aliases) - assert pofile.__unicode__() == '''# + assert pofile == '''# msgid "" msgstr "" @@ -53,7 +53,7 @@ def test_disable_enable_raw_inline(): This must be included also. ''' pofile = markdown_to_pofile(content) - assert pofile.__unicode__() == '''# + assert pofile == '''# msgid "" msgstr "" @@ -94,7 +94,7 @@ def test_enable_next_line(command, command_aliases): ''' pofile = markdown_to_pofile(content, command_aliases=command_aliases) - assert pofile.__unicode__() == '''# + assert pofile == '''# msgid "" msgstr "" @@ -131,7 +131,7 @@ def test_disable_next_line(command, command_aliases): This must be included also. ''' pofile = markdown_to_pofile(content, command_aliases=command_aliases) - assert pofile.__unicode__() == '''# + assert pofile == '''# msgid "" msgstr "" diff --git a/test/test_md2po/test_commands/test_md2po_include.py b/test/test_md2po/test_commands/test_md2po_include.py index 77e04901..b511658d 100644 --- a/test/test_md2po/test_commands/test_md2po_include.py +++ b/test/test_md2po/test_commands/test_md2po_include.py @@ -16,7 +16,7 @@ def test_include_comment(command, command_aliases): Some text without comment ''' pofile = markdown_to_pofile(content, command_aliases=command_aliases) - assert pofile.__unicode__() == '''# + assert pofile == '''# msgid "" msgstr "" @@ -53,7 +53,7 @@ def test_include_comment_with_extracted(): Some text without comment ''' pofile = markdown_to_pofile(content) - assert pofile.__unicode__() == '''# + assert pofile == '''# msgid "" msgstr "" @@ -78,7 +78,7 @@ def test_include_comment_with_extracted_and_context(): Some text without comment ''' pofile = markdown_to_pofile(content) - assert pofile.__unicode__() == '''# + assert pofile == '''# msgid "" msgstr "" diff --git a/test/test_md2po/test_commands/test_md2po_translator.py b/test/test_md2po/test_commands/test_md2po_translator.py index 2fcd9a56..b2f78b9b 100644 --- a/test/test_md2po/test_commands/test_md2po_translator.py +++ b/test/test_md2po/test_commands/test_md2po_translator.py @@ -17,7 +17,7 @@ def test_translator_command_paragraph(command, command_aliases): ''' pofile = markdown_to_pofile(content, command_aliases=command_aliases) - assert pofile.__unicode__() == '''# + assert pofile == '''# msgid "" msgstr "" diff --git a/test/test_md2po/test_extract.py b/test/test_md2po/test_extract.py index 8b9fb812..c2531357 100644 --- a/test/test_md2po/test_extract.py +++ b/test/test_md2po/test_extract.py @@ -14,7 +14,7 @@ def _build_examples(dirname): examples_dir = os.path.join(EXAMPLES_DIR, dirname) - examples_glob = glob.glob(examples_dir + os.sep + '*.md') + examples_glob = glob.glob(os.path.join(examples_dir, '*.md')) examples_filenames = sorted(os.path.basename(fp) for fp in examples_glob) return (examples_dir, examples_filenames) @@ -33,8 +33,8 @@ def test_extract_plaintext(filename): filepath = os.path.join(EXAMPLES['plaintext']['dirpath'], filename) pofile = markdown_to_pofile(filepath, plaintext=True, location=False) - with open(filepath + '.expect.po') as expect_file: - assert pofile.__unicode__() == expect_file.read() + with open(f'{filepath}.expect.po') as expect_file: + assert str(pofile) == expect_file.read() @pytest.mark.parametrize('filename', EXAMPLES['markuptext']['filenames']) @@ -42,8 +42,8 @@ def test_extract_markuptext(filename): filepath = os.path.join(EXAMPLES['markuptext']['dirpath'], filename) pofile = markdown_to_pofile(filepath, plaintext=False, location=False) - with open(filepath + '.expect.po') as expect_file: - assert pofile.__unicode__() == expect_file.read() + with open(f'{filepath}.expect.po') as expect_file: + assert str(pofile) == expect_file.read() @pytest.mark.parametrize('filename', EXAMPLES['underline']['filenames']) @@ -56,8 +56,8 @@ def test_extract_underline(filename): location=False, ) - with open(filepath + '.expect.po') as expect_file: - assert pofile.__unicode__() == expect_file.read() + with open(f'{filepath}.expect.po') as expect_file: + assert str(pofile) == expect_file.read() @pytest.mark.parametrize( @@ -66,17 +66,15 @@ def test_extract_underline(filename): def test_extract_save(filename): filepath = os.path.join(EXAMPLES['plaintext']['dirpath'], filename) - save_file = tempfile.NamedTemporaryFile(suffix='.po') + with tempfile.NamedTemporaryFile(suffix='.po') as save_file: - markdown_to_pofile( - filepath, - plaintext=True, - save=True, - po_filepath=save_file.name, - location=False, - ) - save_file.seek(0) + markdown_to_pofile( + filepath, + plaintext=True, + save=True, + po_filepath=save_file.name, + location=False, + ) - with open(filepath + '.expect.po') as expect_file: - assert save_file.read().decode('utf-8') == expect_file.read() - save_file.close() + with open(f'{filepath}.expect.po') as expect_file: + assert save_file.read().decode('utf-8') == expect_file.read() diff --git a/test/test_md2po/test_extractor.py b/test/test_md2po/test_extractor.py index 4195abf6..f9572a4d 100644 --- a/test/test_md2po/test_extractor.py +++ b/test/test_md2po/test_extractor.py @@ -16,7 +16,7 @@ def test_content_extractor(): ''' md2po = Md2Po(markdown_content) - assert md2po.extract().__unicode__() == '''# + assert str(md2po.extract()) == '''# msgid "" msgstr "" @@ -34,12 +34,12 @@ def test_mark_not_found_as_obsolete(tmp_file): 'Another string\n\n' ) new_md_file_content = 'A new string\n' - po_file = tempfile.NamedTemporaryFile(suffix='.po') - with tmp_file(original_md_file_content, '.md') as original_md_filepath: - md2po = Md2Po(original_md_filepath) - po = md2po.extract(po_filepath=po_file.name, save=True) - assert po.__unicode__() == f'''# + with tempfile.NamedTemporaryFile(suffix='.po') as po_file: + with tmp_file(original_md_file_content, '.md') as original_md_filepath: + md2po = Md2Po(original_md_filepath) + pofile = md2po.extract(po_filepath=po_file.name, save=True) + assert pofile == f'''# msgid "" msgstr "" @@ -52,13 +52,13 @@ def test_mark_not_found_as_obsolete(tmp_file): msgstr "" ''' - with tmp_file(new_md_file_content, '.md') as new_md_filepath: - md2po = Md2Po( - new_md_filepath, - mark_not_found_as_obsolete=True, - ) - po = md2po.extract(po_filepath=po_file.name) - assert po.__unicode__() == f'''# + with tmp_file(new_md_file_content, '.md') as new_md_filepath: + md2po = Md2Po( + new_md_filepath, + mark_not_found_as_obsolete=True, + ) + pofile = md2po.extract(po_filepath=po_file.name) + assert pofile == f'''# msgid "" msgstr "" @@ -73,13 +73,11 @@ def test_mark_not_found_as_obsolete(tmp_file): #~ msgstr "" ''' - po_file.close() - def test_msgstr(): content = 'Mensaje por defecto' md2po = Md2Po(content, msgstr='Default message') - assert md2po.extract(content).__unicode__() == '''# + assert str(md2po.extract(content)) == '''# msgid "" msgstr "" @@ -91,7 +89,7 @@ def test_msgstr(): def test_ignore_msgids(): content = 'foo\n\nbar\n\nbaz\n' md2po = Md2Po(content, ignore_msgids=['foo', 'baz']) - assert md2po.extract(content).__unicode__() == '''# + assert str(md2po.extract(content)) == '''# msgid "" msgstr "" diff --git a/test/test_md2po/test_md2po_cli.py b/test/test_md2po/test_md2po_cli.py index 80552f7a..2c154acd 100644 --- a/test/test_md2po/test_md2po_cli.py +++ b/test/test_md2po/test_md2po_cli.py @@ -24,20 +24,21 @@ msgid "Some text here" msgstr "" + ''', } -def test_stdin(striplastline, capsys, monkeypatch): +def test_stdin(capsys, monkeypatch): monkeypatch.setattr('sys.stdin', io.StringIO(EXAMPLE['input'])) pofile, exitcode = run() - out, err = capsys.readouterr() + stdout, _ = capsys.readouterr() assert exitcode == 0 - assert pofile.__unicode__() == EXAMPLE['output'] - assert striplastline(out) == EXAMPLE['output'] + assert f'{pofile}\n' == EXAMPLE['output'] + assert stdout == EXAMPLE['output'] -def test_stdin_subprocess_input(striplastline, tmp_file): +def test_stdin_subprocess_input(tmp_file): proc = subprocess.run( 'md2po', universal_newlines=True, @@ -46,7 +47,7 @@ def test_stdin_subprocess_input(striplastline, tmp_file): check=True, ) assert proc.returncode == 0 - assert striplastline(proc.stdout) == EXAMPLE['output'] + assert proc.stdout == EXAMPLE['output'] with tmp_file(EXAMPLE['input'], '.md') as mdfile_path: proc = subprocess.run( @@ -57,11 +58,11 @@ def test_stdin_subprocess_input(striplastline, tmp_file): check=True, ) assert proc.returncode == 0 - assert striplastline(proc.stdout) == EXAMPLE['output'] + assert proc.stdout == EXAMPLE['output'] @pytest.mark.skipif(sys.platform != 'linux', reason='Linux only test') -def test_pipe_redirect_file_stdin(striplastline, tmp_file): +def test_pipe_redirect_file_stdin(tmp_file): with tmp_file(EXAMPLE['input'], '.md') as mdfile_path: proc = subprocess.run( f'< {mdfile_path} md2po', @@ -71,32 +72,33 @@ def test_pipe_redirect_file_stdin(striplastline, tmp_file): stderr=subprocess.PIPE, shell=True, ) - assert striplastline(proc.stdout) == EXAMPLE['output'] + assert proc.stdout == EXAMPLE['output'] assert proc.returncode == 0 @pytest.mark.parametrize('arg', ['-q', '--quiet']) def test_quiet(capsys, arg): pofile, exitcode = run([EXAMPLE['input'], arg]) - out, err = capsys.readouterr() + stdout, stderr = capsys.readouterr() assert exitcode == 0 - assert pofile.__unicode__() == EXAMPLE['output'] - assert out == '' + assert f'{pofile}\n' == EXAMPLE['output'] + assert stdout == '' + assert stderr == '' @pytest.mark.parametrize('arg', ['-D', '--debug']) def test_debug(capsys, arg): pofile, exitcode = run([EXAMPLE['input'], arg]) - out, err = capsys.readouterr() + stdout, _ = capsys.readouterr() assert exitcode == 0 - assert pofile.__unicode__() == EXAMPLE['output'] + assert f'{pofile}\n' == EXAMPLE['output'] po_output_checked = False - outlines = out.splitlines() - for i, line in enumerate(outlines): + stdout_lines = stdout.splitlines() + for i, line in enumerate(stdout_lines): assert re.match( ( r'^md2po\[DEBUG\]::\d{4,}-\d\d-\d\d\s\d\d:\d\d:\d\d\.\d+::' @@ -106,7 +108,7 @@ def test_debug(capsys, arg): line, ) if line.endswith('msgid=\'\''): - assert '\n'.join(outlines[i + 1:]) == EXAMPLE['output'] + assert '\n'.join([*stdout_lines[i + 1:], '']) == EXAMPLE['output'] po_output_checked = True break @@ -114,7 +116,7 @@ def test_debug(capsys, arg): @pytest.mark.parametrize('arg', ['-po', '--po-filepath', '--pofilepath']) -def test_po_filepath(striplastline, capsys, arg, tmp_file): +def test_po_filepath(capsys, arg, tmp_file): pofile_content = '''# msgid "" msgstr "" @@ -131,6 +133,7 @@ def test_po_filepath(striplastline, capsys, arg, tmp_file): msgid "Bar" msgstr "" + ''' with tmp_file(pofile_content, '.po') as pofile_path: @@ -141,15 +144,15 @@ def test_po_filepath(striplastline, capsys, arg, tmp_file): '-m', '--no-location', ]) - out, err = capsys.readouterr() + stdout, _ = capsys.readouterr() assert exitcode == 0 - assert pofile.__unicode__() == expected_output - assert striplastline(out) == expected_output + assert f'{pofile}\n' == expected_output + assert stdout == expected_output @pytest.mark.parametrize('arg', ['-s', '--save']) -def test_save(striplastline, capsys, arg, tmp_file): +def test_save(capsys, arg, tmp_file): pofile_content = '''# msgid "" msgstr "" @@ -166,6 +169,7 @@ def test_save(striplastline, capsys, arg, tmp_file): msgid "Bar" msgstr "" + ''' with tmp_file(pofile_content, '.po') as pofile_path: @@ -177,14 +181,14 @@ def test_save(striplastline, capsys, arg, tmp_file): '-m', '--no-location', ]) - out, err = capsys.readouterr() with open(pofile_path) as f: - assert f.read() == expected_output + assert f'{f.read()}\n' == expected_output + stdout, _ = capsys.readouterr() assert exitcode == 0 - assert pofile.__unicode__() == expected_output - assert striplastline(out) == expected_output + assert f'{pofile}\n' == expected_output + assert stdout == expected_output # new PO file creation pofile_path = os.path.join(tempfile.gettempdir(), uuid4().hex[:8]) @@ -196,7 +200,6 @@ def test_save(striplastline, capsys, arg, tmp_file): '-m', '--no-location', ]) - out, err = capsys.readouterr() expected_output = '''# msgid "" @@ -204,33 +207,30 @@ def test_save(striplastline, capsys, arg, tmp_file): msgid "Bar" msgstr "" + ''' with open(pofile_path) as f: - assert f.read() == expected_output + assert f'{f.read()}\n' == expected_output + stdout, _ = capsys.readouterr() assert exitcode == 0 - assert pofile.__unicode__() == expected_output - assert striplastline(out) == expected_output + assert f'{pofile}\n' == expected_output + assert stdout == expected_output @pytest.mark.parametrize('arg', ['-mo', '--mo-filepath', '--mofilepath']) -def test_mo_filepath(striplastline, capsys, arg): - mo_file = tempfile.NamedTemporaryFile(suffix='.mo') - mo_filepath = mo_file.name - mo_file.close() - - pofile, exitcode = run([EXAMPLE['input'], arg, mo_filepath]) - out, err = capsys.readouterr() - assert exitcode == 0 - assert pofile.__unicode__() == EXAMPLE['output'] - assert striplastline(out) == EXAMPLE['output'] - assert os.path.exists(mo_filepath) - - os.remove(mo_filepath) +def test_mo_filepath(capsys, arg): + with tempfile.NamedTemporaryFile(suffix='.mo') as mo_file: + pofile, exitcode = run([EXAMPLE['input'], arg, mo_file.name]) + stdout, _ = capsys.readouterr() + assert exitcode == 0 + assert f'{pofile}\n' == EXAMPLE['output'] + assert stdout == EXAMPLE['output'] + assert os.path.exists(mo_file.name) @pytest.mark.parametrize('arg', ['-i', '--ignore']) -def test_ignore_files_by_filepath(striplastline, capsys, arg): +def test_ignore_files_by_filepath(capsys, arg): filesdata = { 'foo': '### Foo\n\nFoo 2', 'bar': '## Bar with `inline code`', @@ -239,8 +239,7 @@ def test_ignore_files_by_filepath(striplastline, capsys, arg): with tempfile.TemporaryDirectory() as filesdir: for filename, content in filesdata.items(): - filepath = os.path.join(filesdir, filename + '.md') - with open(filepath, 'w') as f: + with open(os.path.join(filesdir, f'{filename}.md'), 'w') as f: f.write(content) _glob = os.path.join(filesdir, '*.md') @@ -252,7 +251,6 @@ def test_ignore_files_by_filepath(striplastline, capsys, arg): os.path.join(filesdir, 'baz.md'), '--no-location', ]) - out, err = capsys.readouterr() expected_output = '''# msgid "" @@ -263,22 +261,22 @@ def test_ignore_files_by_filepath(striplastline, capsys, arg): msgid "Foo 2" msgstr "" + ''' + + stdout, _ = capsys.readouterr() assert exitcode == 0 - assert pofile.__unicode__() == expected_output - assert striplastline(out) == expected_output + assert f'{pofile}\n' == expected_output + assert stdout == expected_output -def test_markuptext(striplastline, capsys): +def test_markuptext(capsys): content = ( '# Header `with inline code`\n\n' 'Some text with **bold characters**, *italic characters*' ' and a [link](https://nowhere.nothing).\n' ) - pofile, exitcode = run([content]) - out, err = capsys.readouterr() - expected_output = '''# msgid "" msgstr "" @@ -290,43 +288,43 @@ def test_markuptext(striplastline, capsys): "Some text with **bold characters**, *italic characters* and a " "[link](https://nowhere.nothing)." msgstr "" + ''' + pofile, exitcode = run([content]) + stdout, _ = capsys.readouterr() assert exitcode == 0 - assert pofile.__unicode__() == expected_output - assert striplastline(out) == expected_output + assert f'{pofile}\n' == expected_output + assert stdout == expected_output @pytest.mark.parametrize('arg', ['-w', '--wrapwidth']) @pytest.mark.parametrize('value', ['0', 'inf']) -def test_wrapwidth(striplastline, capsys, arg, value): +def test_wrapwidth(capsys, arg, value): content = ( '# Some long header with **bold characters**, ' '*italic characters* and a [link](https://nowhere.nothing).\n' ) - - pofile, exitcode = run([content, arg, value, '-p']) - out, err = capsys.readouterr() - expected_output = '''# msgid "" msgstr "" msgid "Some long header with bold characters, italic characters and a link." msgstr "" + ''' + + pofile, exitcode = run([content, arg, value, '-p']) + stdout, _ = capsys.readouterr() + assert exitcode == 0 - assert pofile.__unicode__() == expected_output - assert striplastline(out) == expected_output + assert f'{pofile}\n' == expected_output + assert stdout == expected_output @pytest.mark.parametrize('arg', ['-a', '--xheaders']) -def test_xheaders(striplastline, capsys, arg): +def test_xheaders(capsys, arg): markdown_content = '# Foo' - - pofile, exitcode = run([markdown_content, arg]) - out, err = capsys.readouterr() - expected_output = '''# msgid "" msgstr "" @@ -347,15 +345,19 @@ def test_xheaders(striplastline, capsys, arg): msgid "Foo" msgstr "" + ''' + pofile, exitcode = run([markdown_content, arg]) + stdout, _ = capsys.readouterr() + assert exitcode == 0 - assert pofile.__unicode__() == expected_output - assert striplastline(out) == expected_output + assert f'{pofile}\n' == expected_output + assert stdout == expected_output @pytest.mark.parametrize('arg', ['-c', '--include-codeblocks']) -def test_include_codeblocks(striplastline, capsys, arg): +def test_include_codeblocks(capsys, arg): markdown_content = ''' var hello = "world"; @@ -365,8 +367,6 @@ def test_include_codeblocks(striplastline, capsys, arg): This must be included also. ''' - pofile, exitcode = run([markdown_content, arg]) - out, err = capsys.readouterr() expected_output = '''# msgid "" @@ -380,34 +380,39 @@ def test_include_codeblocks(striplastline, capsys, arg): msgid "This must be included also." msgstr "" + ''' + pofile, exitcode = run([markdown_content, arg]) + stdout, _ = capsys.readouterr() + assert exitcode == 0 - assert striplastline(out) == expected_output - assert pofile.__unicode__() == expected_output + assert f'{pofile}\n' == expected_output + assert stdout == expected_output @pytest.mark.parametrize('arg', ['--ignore-msgids']) -def test_ignore_msgids(striplastline, capsys, arg, tmp_file): +def test_ignore_msgids(capsys, arg, tmp_file): expected_output = '''# msgid "" msgstr "" msgid "bar" msgstr "" + ''' with tmp_file('foo\nbaz', '.txt') as filename: pofile, exitcode = run(['foo\n\nbar\n\nbaz\n', arg, filename]) - out, err = capsys.readouterr() + stdout, _ = capsys.readouterr() assert exitcode == 0 - assert striplastline(out) == expected_output - assert pofile.__unicode__() == expected_output + assert f'{pofile}\n' == expected_output + assert stdout == expected_output @pytest.mark.parametrize('arg', ['--command-alias']) -def test_command_aliases(striplastline, capsys, arg, tmp_file): +def test_command_aliases(capsys, arg, tmp_file): markdown_content = ''' This should be ignored. @@ -426,6 +431,7 @@ def test_command_aliases(striplastline, capsys, arg, tmp_file): msgid "This should be included." msgstr "" + ''' pofile, exitcode = run([ @@ -433,15 +439,15 @@ def test_command_aliases(striplastline, capsys, arg, tmp_file): arg, 'mdpo-on:mdpo-enable', arg, '\\:off:mdpo-disable', ]) - out, err = capsys.readouterr() + stdout, _ = capsys.readouterr() assert exitcode == 0 - assert striplastline(out) == expected_output - assert pofile.__unicode__() == expected_output + assert f'{pofile}\n' == expected_output + assert stdout == expected_output @pytest.mark.parametrize('arg', ['-d', '--metadata']) -def test_metadata(striplastline, capsys, arg, tmp_file): +def test_metadata(capsys, arg, tmp_file): expected_output = '''# msgid "" msgstr "" @@ -450,6 +456,7 @@ def test_metadata(striplastline, capsys, arg, tmp_file): msgid "Some content" msgstr "" + ''' pofile, exitcode = run([ @@ -457,15 +464,15 @@ def test_metadata(striplastline, capsys, arg, tmp_file): arg, 'Language: es', arg, 'Content-Type: text/plain; charset=utf-8', ]) - out, err = capsys.readouterr() + stdout, _ = capsys.readouterr() assert exitcode == 0 - assert striplastline(out) == expected_output - assert pofile.__unicode__() == expected_output + assert f'{pofile}\n' == expected_output + assert stdout == expected_output @pytest.mark.parametrize('arg', ('-m', '--merge-pofiles', '--merge-po-files')) -def test_merge_pofiles(striplastline, capsys, arg, tmp_file): +def test_merge_pofiles(capsys, arg, tmp_file): md_content = '# bar\n\n\nbaz\n' pofile_content = '''# msgid "" @@ -487,6 +494,7 @@ def test_merge_pofiles(striplastline, capsys, arg, tmp_file): msgid "baz" msgstr "" + ''' with tmp_file(pofile_content, '.po') as po_filepath: @@ -495,15 +503,15 @@ def test_merge_pofiles(striplastline, capsys, arg, tmp_file): '--po-filepath', po_filepath, arg, ]) - out, err = capsys.readouterr() + stdout, _ = capsys.readouterr() assert exitcode == 0 - assert striplastline(out) == expected_output - assert pofile.__unicode__() == expected_output + assert f'{pofile}\n' == expected_output + assert stdout == expected_output @pytest.mark.parametrize('arg', ('-r', '--remove-not-found')) -def test_remove_not_found(striplastline, capsys, arg, tmp_file): +def test_remove_not_found(capsys, arg, tmp_file): md_content = '# bar\n\n\nbaz\n' pofile_content = '''# msgid "" @@ -522,6 +530,7 @@ def test_remove_not_found(striplastline, capsys, arg, tmp_file): msgid "baz" msgstr "" + ''' with tmp_file(pofile_content, '.po') as po_filepath: @@ -532,11 +541,11 @@ def test_remove_not_found(striplastline, capsys, arg, tmp_file): arg, '--merge-pofiles', ]) - out, err = capsys.readouterr() + stdout, _ = capsys.readouterr() assert exitcode == 0 - assert striplastline(out) == expected_output - assert pofile.__unicode__() == expected_output + assert f'{pofile}\n' == expected_output + assert stdout == expected_output @pytest.mark.parametrize('arg', ('-x', '--extension', '--ext')) @@ -564,6 +573,7 @@ def test_remove_not_found(striplastline, capsys, arg, tmp_file): msgid "Qux" msgstr "" + ''', id='tables (included by default)', ), @@ -579,6 +589,7 @@ def test_remove_not_found(striplastline, capsys, arg, tmp_file): msgid "| Foo | Bar | | :-: | :-: | | Baz | Qux |" msgstr "" + ''', id='strikethrough (overwrite default extensions)', ), @@ -589,7 +600,6 @@ def test_extensions( extensions, md_content, expected_output, - striplastline, capsys, ): extensions_arguments = [] @@ -598,11 +608,11 @@ def test_extensions( extensions_arguments.extend([arg, extension]) pofile, exitcode = run([md_content, *extensions_arguments]) - out, err = capsys.readouterr() + stdout, _ = capsys.readouterr() assert exitcode == 0 - assert striplastline(out) == expected_output - assert pofile.__unicode__() == expected_output + assert f'{pofile}\n' == expected_output + assert stdout == expected_output @pytest.mark.parametrize( @@ -610,15 +620,15 @@ def test_extensions( (None, 'foo'), ids=('_MDPO_RUNNING=', '_MDPO_RUNNING=foo'), ) -def test_md2po_cli_running_osenv(striplastline, value, capsys): +def test_md2po_cli_running_osenv(value, capsys): if value is not None: os.environ['_MDPO_RUNNING'] = value pofile, exitcode = run([EXAMPLE['input']]) - out, err = capsys.readouterr() + stdout, _ = capsys.readouterr() assert exitcode == 0 - assert pofile.__unicode__() == EXAMPLE['output'] - assert striplastline(out) == EXAMPLE['output'] + assert f'{pofile}\n' == EXAMPLE['output'] + assert stdout == EXAMPLE['output'] assert os.environ.get('_MDPO_RUNNING') == value diff --git a/test/test_md2po/test_md2po_events.py b/test/test_md2po/test_md2po_events.py index 291d120d..6d6631de 100644 --- a/test/test_md2po/test_md2po_events.py +++ b/test/test_md2po/test_md2po_events.py @@ -61,10 +61,9 @@ def test_enter_block_event(abort_event): ), ) def test_enter_leave_span_event(abort_event, expected_msgid): - content = 'Hello `with` codespan' - po = markdown_to_pofile( + pofile = markdown_to_pofile( content, events={ 'enter_span': lambda *_: not abort_event, @@ -72,7 +71,7 @@ def test_enter_leave_span_event(abort_event, expected_msgid): }, ) - assert str(po).splitlines()[4].split('"')[1] == expected_msgid + assert str(pofile).splitlines()[4].split('"')[1] == expected_msgid @pytest.mark.parametrize(('abort_event'), (True, False)) @@ -101,6 +100,8 @@ def error_when_unknown_command_event( comment, original_command, ): + # here 'normalize_mdpo_command' is added to simulate a real behaviour, + # is not related with the test itself if normalize_mdpo_command(command) is None and abort_event: raise ValueError('unhandled command for testing') @@ -121,6 +122,62 @@ def error_when_unknown_command_event( md2po.extract() +def test_command_event_return_false(): + def skip_counter_command_event( + self, + command, + comment, + original_command, + ): + if command == 'mdpo-skip': + self.skip_counter += 1 + return False + elif command == 'mdpo-disable-next-line': + return False + + content = ''' + +some text + +mdpo-skip + + + + + +This must be included in output +''' + + # Md2Po must be subclassed because is defined with fixed slots + class CustomMd2Po(Md2Po): + def __init__(self, *args, **kwargs): + self.skip_counter = 0 + super().__init__(*args, **kwargs) + + md2po = CustomMd2Po( + content, + events={ + 'command': skip_counter_command_event, + }, + ) + output = md2po.extract() + + assert md2po.skip_counter == content.count('') + assert output == '''# +msgid "" +msgstr "" + +msgid "some text" +msgstr "" + +msgid "mdpo-skip" +msgstr "" + +msgid "This must be included in output" +msgstr "" +''' + + def test_msgid_event(): def dont_save_hate_msgid(self, msgid, *args): if msgid == 'hate': diff --git a/test/test_md2po/test_obsoletes.py b/test/test_md2po/test_obsoletes.py index b177c5d9..df42036f 100644 --- a/test/test_md2po/test_obsoletes.py +++ b/test/test_md2po/test_obsoletes.py @@ -47,12 +47,14 @@ def test_obsolete_not_equal_found( pofile_content = '#\nmsgid ""\nmsgstr ""\n\nmsgid "Bar"\nmsgstr ""\n' with tmp_file(pofile_content, '.po') as po_filepath: - output = markdown_to_pofile( - markdown_content, - po_filepath=po_filepath, - mark_not_found_as_obsolete=mark_not_found_as_obsolete, - location=False, - ).__unicode__() + output = str( + markdown_to_pofile( + markdown_content, + po_filepath=po_filepath, + mark_not_found_as_obsolete=mark_not_found_as_obsolete, + location=False, + ), + ) assert output == expected_output @@ -75,11 +77,13 @@ def test_obsolete_msgstr_fallback(tmp_file, default_msgstr): msgid "Hello" msgstr "Hola" ''' - output = markdown_to_pofile( - markdown_content, - po_filepath=po_filepath, - msgstr=default_msgstr, - ).__unicode__() + output = str( + markdown_to_pofile( + markdown_content, + po_filepath=po_filepath, + msgstr=default_msgstr, + ), + ) assert output == expected_output @@ -106,11 +110,13 @@ def test_fuzzy_obsolete_msgstr_fallback(tmp_file, default_msgstr): msgstr "Hola" ''' - output = markdown_to_pofile( - markdown_content, - po_filepath=po_filepath, - msgstr=default_msgstr, - ).__unicode__() + output = str( + markdown_to_pofile( + markdown_content, + po_filepath=po_filepath, + msgstr=default_msgstr, + ), + ) assert output == expected_output @@ -140,9 +146,13 @@ def test_tcomment_obsolete_msgstr_fallback_without_found_tcomment( msgstr "Hola" ''' - output = markdown_to_pofile( - markdown_content, po_filepath=po_filepath, msgstr=default_msgstr, - ).__unicode__() + output = str( + markdown_to_pofile( + markdown_content, + po_filepath=po_filepath, + msgstr=default_msgstr, + ), + ) assert output == expected_output @@ -175,9 +185,13 @@ def test_tcomment_obsolete_msgstr_fallback_with_found_tcomment( msgstr "Hola" ''' - output = markdown_to_pofile( - markdown_content, po_filepath=po_filepath, msgstr=default_msgstr, - ).__unicode__() + output = str( + markdown_to_pofile( + markdown_content, + po_filepath=po_filepath, + msgstr=default_msgstr, + ), + ) assert output == expected_output @@ -202,10 +216,12 @@ def test_obsolete_with_msgctxt_matching_msgstr_fallback(tmp_file): msgstr "Hola" ''' - output = markdown_to_pofile( - markdown_content, - po_filepath=po_filepath, - ).__unicode__() + output = str( + markdown_to_pofile( + markdown_content, + po_filepath=po_filepath, + ), + ) assert output == expected_output @@ -235,7 +251,10 @@ def test_obsolete_with_msgctxt_not_matching_msgstr_fallback(tmp_file): #~ msgstr "Hola" ''' - output = markdown_to_pofile( - markdown_content, po_filepath=po_filepath, - ).__unicode__() + output = str( + markdown_to_pofile( + markdown_content, + po_filepath=po_filepath, + ), + ) assert output == expected_output diff --git a/test/test_md2po/test_x_headers.py b/test/test_md2po/test_x_headers.py index 73e43462..1ae72d44 100644 --- a/test/test_md2po/test_x_headers.py +++ b/test/test_md2po/test_x_headers.py @@ -6,13 +6,13 @@ def test_x_headers_included(): markdown_content = '# Foo\n' extensions = DEFAULT_MD4C_GENERIC_PARSER_EXTENSIONS + ['underline'] - po = markdown_to_pofile( + pofile = markdown_to_pofile( markdown_content, xheaders=True, plaintext=False, extensions=extensions, ) - assert po.__unicode__() == '''# + assert pofile == '''# msgid "" msgstr "" "x-mdpo-bold-end: **\\n" diff --git a/test/test_mdpo2html/test_mdpo2html_cli.py b/test/test_mdpo2html/test_mdpo2html_cli.py index a7fe7926..14afa894 100644 --- a/test/test_mdpo2html/test_mdpo2html_cli.py +++ b/test/test_mdpo2html/test_mdpo2html_cli.py @@ -26,28 +26,30 @@ def test_stdin(capsys, monkeypatch, tmp_file): monkeypatch.setattr('sys.stdin', io.StringIO(EXAMPLE['html-input'])) - with tmp_file(EXAMPLE['pofile'], '.po') as po_filepath: + with tmp_file(EXAMPLE['pofile'], '.po') as po_filepath: output, exitcode = run(['-p', po_filepath]) - out, err = capsys.readouterr() + stdout, stderr = capsys.readouterr() assert exitcode == 0 assert output == EXAMPLE['html-output'][:-1] # rstrip("\n") - assert out == EXAMPLE['html-output'] + assert stdout == EXAMPLE['html-output'] + assert stderr == '' @pytest.mark.parametrize('arg', ['-q', '--quiet']) def test_quiet(capsys, arg, tmp_file): with tmp_file(EXAMPLE['pofile'], '.po') as po_filepath: - output, exitcode = run([ EXAMPLE['html-input'], '-p', po_filepath, arg, ]) - out, err = capsys.readouterr() + stdout, stderr = capsys.readouterr() assert exitcode == 0 assert output == EXAMPLE['html-output'] + assert stdout == '' + assert stderr == '' @pytest.mark.parametrize('arg', ['-s', '--save']) @@ -60,11 +62,11 @@ def test_save(capsys, arg, tmp_file): html_input_filepath, '-p', po_filepath, arg, html_output_filepath, ]) - out, err = capsys.readouterr() + stdout, _ = capsys.readouterr() assert exitcode == 0 assert output == EXAMPLE['html-output'] - assert out == '' + assert stdout == '' with open(html_output_filepath) as f: output_html_content = f.read() @@ -73,52 +75,48 @@ def test_save(capsys, arg, tmp_file): @pytest.mark.parametrize('arg', ['-i', '--ignore']) -def test_ignore_files_by_filepath(striplastline, capsys, arg, tmp_file): - pofiles = [ +def test_ignore_files_by_filepath(capsys, arg, tmp_file): + pofiles_contents = [ ( - uuid4().hex + '.po', - ( - '#\nmsgid ""\nmsgstr ""\n\nmsgid "Included"\n' - 'msgstr "Incluida"\n\n' - ), + '#\nmsgid ""\nmsgstr ""\n\nmsgid "Included"\n' + 'msgstr "Incluida"\n\n' ), ( - uuid4().hex + '.po', - ( - '#\nmsgid ""\nmsgstr ""\n\nmsgid "Exluded"\n' - 'msgstr "Excluida"\n\n' - ), + '#\nmsgid ""\nmsgstr ""\n\nmsgid "Exluded"\n' + 'msgstr "Excluida"\n\n' ), ( - uuid4().hex + '.po', - ( - '#\nmsgid ""\nmsgstr ""\n\nmsgid "Exluded 2"\n' - 'msgstr "Excluida 2"\n\n' - ), + '#\nmsgid ""\nmsgstr ""\n\nmsgid "Exluded 2"\n' + 'msgstr "Excluida 2"\n\n' ), ] html_input = '

Included

\n\n

Excluded

\n\n

Excluded 2

\n\n' expected_output = ( - '

Incluida

\n\n

Excluded

\n\n

Excluded 2

\n\n' + '

Incluida

\n\n

Excluded

\n\n

Excluded 2

\n\n\n' ) with tempfile.TemporaryDirectory() as filesdir: - for pofile in pofiles: - with open(os.path.join(filesdir, pofile[0]), 'w') as f: - f.write(pofile[1]) + pofiles_paths = [ + os.path.join(filesdir, f'{uuid4().hex}.po') + for _ in range(len(pofiles_contents)) + ] + pofiles_paths_contents = zip(pofiles_paths, pofiles_contents) + for pofile_path, pofile_content in pofiles_paths_contents: + with open(pofile_path, 'w') as f: + f.write(pofile_content) with tmp_file(html_input, '.html') as html_input_filepath: output, exitcode = run([ html_input_filepath, '-p', os.path.join(filesdir, '*.po'), arg, - pofiles[1][0], + pofiles_paths[1], arg, - pofiles[2][0], + pofiles_paths[2], ]) - out, err = capsys.readouterr() + stdout, _ = capsys.readouterr() assert exitcode == 0 - assert output == expected_output - assert striplastline(out) == expected_output + assert f'{output}\n' == expected_output + assert stdout == expected_output diff --git a/test/test_po2md/test_po2md_cli.py b/test/test_po2md/test_po2md_cli.py index 2ed0cc78..21d759d7 100644 --- a/test/test_po2md/test_po2md_cli.py +++ b/test/test_po2md/test_po2md_cli.py @@ -13,7 +13,7 @@ EXAMPLE = { 'markdown-input': '# Header 1\n\nSome text here\n', - 'markdown-output': '# Encabezado 1\n\nAlgo de texto aquí\n', + 'markdown-output': '# Encabezado 1\n\nAlgo de texto aquí\n\n', 'pofile': '''# msgid "" msgstr "" @@ -27,16 +27,15 @@ } -def test_stdin(striplastline, capsys, monkeypatch, tmp_file): +def test_stdin(capsys, monkeypatch, tmp_file): monkeypatch.setattr('sys.stdin', io.StringIO(EXAMPLE['markdown-input'])) with tmp_file(EXAMPLE['pofile'], '.po') as po_filepath: - output, exitcode = run(['-p', po_filepath]) - out, err = capsys.readouterr() + stdout, _ = capsys.readouterr() assert exitcode == 0 - assert output == EXAMPLE['markdown-output'] - assert striplastline(out) == EXAMPLE['markdown-output'] + assert f'{output}\n' == EXAMPLE['markdown-output'] + assert stdout == EXAMPLE['markdown-output'] @pytest.mark.parametrize('arg', ['-q', '--quiet']) @@ -47,11 +46,12 @@ def test_quiet(capsys, arg, tmp_file): EXAMPLE['markdown-input'], '-p', po_filepath, arg, ]) - out, err = capsys.readouterr() + stdout, stderr = capsys.readouterr() assert exitcode == 0 - assert output == EXAMPLE['markdown-output'] - assert out == '' + assert f'{output}\n' == EXAMPLE['markdown-output'] + assert stdout == '' + assert stderr == '' @pytest.mark.parametrize('arg', ['-D', '--debug']) @@ -60,14 +60,13 @@ def test_debug(capsys, arg, tmp_file): tmp_file(EXAMPLE['markdown-input'], '.md') as input_md_filepath: output, exitcode = run([input_md_filepath, '-p', po_filepath, arg]) - out, err = capsys.readouterr() assert exitcode == 0 - assert output == EXAMPLE['markdown-output'] + assert f'{output}\n' == EXAMPLE['markdown-output'] md_output_checked = False - - outlines = out.splitlines() + stdout, _ = capsys.readouterr() + outlines = stdout.splitlines() for i, line in enumerate(outlines): assert re.match( ( @@ -78,9 +77,9 @@ def test_debug(capsys, arg, tmp_file): line, ) if line.endswith('leave_block:: DOC'): - assert ( - '\n'.join(outlines[i + 1:]) == EXAMPLE['markdown-output'] - ) + non_debug_lines = '\n'.join([*outlines[i + 1:], '']) + assert non_debug_lines == EXAMPLE['markdown-output'] + md_output_checked = True break @@ -97,20 +96,18 @@ def test_save(capsys, arg, tmp_file): input_md_filepath, '-p', po_filepath, arg, output_md_filepath, ]) - out, err = capsys.readouterr() + stdout, _ = capsys.readouterr() assert exitcode == 0 - assert output == EXAMPLE['markdown-output'] - assert out == '' + assert f'{output}\n' == EXAMPLE['markdown-output'] + assert stdout == '' with open(output_md_filepath) as f: - output_markdown_content = f.read() - - assert output_markdown_content == EXAMPLE['markdown-output'] + assert f'{f.read()}\n' == EXAMPLE['markdown-output'] @pytest.mark.parametrize('arg', ['-i', '--ignore']) -def test_ignore_files_by_filepath(striplastline, capsys, arg): +def test_ignore_files_by_filepath(capsys, arg): pofiles = [ ( uuid4().hex + '.po', @@ -135,7 +132,7 @@ def test_ignore_files_by_filepath(striplastline, capsys, arg): ), ] - expected_output = 'Incluida\n\nExcluded\n\nExcluded 2\n' + expected_output = 'Incluida\n\nExcluded\n\nExcluded 2\n\n' with tempfile.TemporaryDirectory() as filesdir: for pofile in pofiles: @@ -147,15 +144,17 @@ def test_ignore_files_by_filepath(striplastline, capsys, arg): f.write('Included\n\nExcluded\n\nExcluded 2\n') output, exitcode = run([ - input_md_filepath, '-p', + input_md_filepath, + '-p', os.path.join(filesdir, '*.po'), arg, os.path.join(filesdir, pofiles[1][0]), arg, os.path.join(filesdir, pofiles[2][0]), ]) - out, err = capsys.readouterr() + + stdout, _ = capsys.readouterr() assert exitcode == 0 - assert output == expected_output - assert striplastline(out) == expected_output + assert f'{output}\n' == expected_output + assert stdout == expected_output diff --git a/test/test_po2md/test_po2md_translate.py b/test/test_po2md/test_po2md_translate.py index be3b484a..98326dd1 100644 --- a/test/test_po2md/test_po2md_translate.py +++ b/test/test_po2md/test_po2md_translate.py @@ -42,11 +42,9 @@ def test_translate_save(filename): os.path.splitext(os.path.basename(filepath_in))[0] + '.po', ) - save_file = tempfile.NamedTemporaryFile(suffix='.po') + with tempfile.NamedTemporaryFile(suffix='.po') as save_file: - pofile_to_markdown(filepath_in, po_filepath, save=save_file.name) - save_file.seek(0) + pofile_to_markdown(filepath_in, po_filepath, save=save_file.name) - with open(filepath_out) as expect_file: - assert save_file.read().decode('utf-8') == expect_file.read() - save_file.close() + with open(filepath_out) as expect_file: + assert save_file.read().decode('utf-8') == expect_file.read() diff --git a/test/test_po2md/translate-examples/code-blocks.md b/test/test_po2md/translate-examples/code-blocks.md index 91492d83..e030f5f4 100644 --- a/test/test_po2md/translate-examples/code-blocks.md +++ b/test/test_po2md/translate-examples/code-blocks.md @@ -15,6 +15,8 @@ Fenced code block with tildes ~~~ Indented code block + + After empty line !!! note diff --git a/test/test_po2md/translate-examples/code-blocks.md.expect.md b/test/test_po2md/translate-examples/code-blocks.md.expect.md index 91492d83..e030f5f4 100644 --- a/test/test_po2md/translate-examples/code-blocks.md.expect.md +++ b/test/test_po2md/translate-examples/code-blocks.md.expect.md @@ -15,6 +15,8 @@ Fenced code block with tildes ~~~ Indented code block + + After empty line !!! note diff --git a/test/test_po2md/translate-examples/images.md b/test/test_po2md/translate-examples/images.md index 49c85c11..6a0b3c92 100644 --- a/test/test_po2md/translate-examples/images.md +++ b/test/test_po2md/translate-examples/images.md @@ -6,6 +6,12 @@ ![Alt text][id] -[id]: url/to/image "Optional title attribute" +[id]: url/to/image "Optional title attribute" My ![foo bar](/path/to/train.jpg "title") + +[![Image inside inline link](https://image.ext)](https://link.ext) + +[![Image inside referenced link](https://image.ext)][1] + +[1]: https://link-1.ext diff --git a/test/test_po2md/translate-examples/images.md.expect.md b/test/test_po2md/translate-examples/images.md.expect.md index 9f13a785..b4ae89da 100644 --- a/test/test_po2md/translate-examples/images.md.expect.md +++ b/test/test_po2md/translate-examples/images.md.expect.md @@ -7,3 +7,10 @@ ![Texto alternativo](url/to/imagen "Atributo título opcional") Mi ![foo bar](/path/to/tren.jpg "título") + +[![Imagen dentro de link en línea](https://image.ext)](https://enlace.ext) + +[![Imagen dentro de link referenciado](https://imagen.ext)][1] + +[id]: url/a/imagen "Título de atributo opcional" +[1]: https://enlace-1.ext diff --git a/test/test_po2md/translate-examples/images.po b/test/test_po2md/translate-examples/images.po index ee90a31b..26e752f2 100644 --- a/test/test_po2md/translate-examples/images.po +++ b/test/test_po2md/translate-examples/images.po @@ -16,3 +16,15 @@ msgstr "![Texto alternativo](url/to/imagen \"Atributo título opcional\")" msgid "My ![foo bar](/path/to/train.jpg \"title\")" msgstr "Mi ![foo bar](/path/to/tren.jpg \"título\")" + +msgid "[![Image inside inline link](https://image.ext)](https://link.ext)" +msgstr "[![Imagen dentro de link en línea](https://image.ext)](https://enlace.ext)" + +msgid "[![Image inside referenced link](https://image.ext)][1]" +msgstr "[![Imagen dentro de link referenciado](https://imagen.ext)][1]" + +msgid "[id]: url/to/image \"Optional title attribute\"" +msgstr "[id]: url/a/imagen \"Título de atributo opcional\"" + +msgid "[1]: https://link-1.ext" +msgstr "[1]: https://enlace-1.ext" diff --git a/test/test_text.py b/test/test_text.py index 27db85d0..daddff2e 100644 --- a/test/test_text.py +++ b/test/test_text.py @@ -1,8 +1,16 @@ """Tests for mdpo text utilities.""" +import math + import pytest -from mdpo.text import min_not_max_chars_in_a_row, parse_escaped_pair +from mdpo.text import ( + min_not_max_chars_in_a_row, + parse_escaped_pair, + parse_strint_0_inf, + removeprefix, + removesuffix, +) @pytest.mark.parametrize( @@ -54,3 +62,49 @@ def test_parse_escaped_pair( key, value = parse_escaped_pair(text) assert key == expected_key assert value == expected_value + + +@pytest.mark.parametrize( + ('value', 'expected_value', 'expected_error'), + ( + ('1', 1, None), + ('1.1', 1, None), + (-1, math.inf, None), + (-1.1, math.inf, None), + ('-1', math.inf, None), + ('-1.1', math.inf, None), + (0, math.inf, None), + (-0, math.inf, None), + ('a', None, ValueError), + ('inf', math.inf, None), + ('-inf', math.inf, None), + ), +) +def test_parse_strint_0_inf(value, expected_value, expected_error): + if expected_error: + with pytest.raises(expected_error): + parse_strint_0_inf(value) + else: + assert parse_strint_0_inf(value) == expected_value + + +@pytest.mark.parametrize( + ('value', 'prefix', 'expected_value'), + ( + ('foo', 'fo', 'o'), + ('bar', 'fo', 'bar'), + ), +) +def test_removeprefix(value, prefix, expected_value): + assert removeprefix(value, prefix) == expected_value + + +@pytest.mark.parametrize( + ('value', 'suffix', 'expected_value'), + ( + ('foo', 'oo', 'f'), + ('bar', 'fo', 'bar'), + ), +) +def test_removesuffix(value, suffix, expected_value): + assert removesuffix(value, suffix) == expected_value