From 2108fdfebfdc13e38c808a1af901d634ee8e70ed Mon Sep 17 00:00:00 2001 From: 5j9 <5j9@users.noreply.github.com> Date: Fri, 3 Nov 2023 10:53:32 +0330 Subject: [PATCH] chore: use ruff format --- dev/html_tag_names.py | 36 +- dev/profiles/vs_mwpfh.py | 15 +- docs/conf.py | 37 +- pyproject.toml | 8 +- tests/test_argument.py | 10 +- tests/test_cell.py | 4 +- tests/test_comment_bold_italic.py | 11 +- tests/test_externallink.py | 11 +- tests/test_parameter.py | 2 +- tests/test_parser_function.py | 24 +- tests/test_section.py | 2 +- tests/test_spans.py | 15 +- tests/test_table.py | 356 ++++++++++--------- tests/test_tag.py | 4 +- tests/test_template.py | 28 +- tests/test_wikilink.py | 2 +- tests/test_wikilist.py | 16 +- tests/wikitext/test_external_links.py | 6 +- tests/wikitext/test_get_bolds_and_italics.py | 54 +-- tests/wikitext/test_get_lists.py | 2 +- tests/wikitext/test_get_tags.py | 36 +- tests/wikitext/test_pformat.py | 278 +++++++-------- tests/wikitext/test_plain_text.py | 20 +- tests/wikitext/test_sections.py | 9 +- tests/wikitext/test_tables.py | 75 ++-- tests/wikitext/test_wikitext.py | 24 +- wikitextparser/_argument.py | 2 +- wikitextparser/_cell.py | 2 +- wikitextparser/_comment_bold_italic.py | 10 +- wikitextparser/_config.py | 99 +++++- wikitextparser/_externallink.py | 2 +- wikitextparser/_parameter.py | 4 +- wikitextparser/_section.py | 4 +- wikitextparser/_spans.py | 24 +- wikitextparser/_table.py | 4 +- wikitextparser/_tag.py | 18 +- wikitextparser/_wikilink.py | 2 +- wikitextparser/_wikitext.py | 3 +- 38 files changed, 691 insertions(+), 568 deletions(-) diff --git a/dev/html_tag_names.py b/dev/html_tag_names.py index b6dbc941..fb4ba7d8 100644 --- a/dev/html_tag_names.py +++ b/dev/html_tag_names.py @@ -8,19 +8,25 @@ def parse(text: str) -> bytes: - return loads(post('https://www.mediawiki.org/w/api.php', data={ - 'action': 'parse', - 'text': text, - 'title': 'Test', - 'format': 'json', - 'formatversion': 2, - 'prop': 'text', - }).content)['parse']['text'] + return loads( + post( + 'https://www.mediawiki.org/w/api.php', + data={ + 'action': 'parse', + 'text': text, + 'title': 'Test', + 'format': 'json', + 'formatversion': 2, + 'prop': 'text', + }, + ).content + )['parse']['text'] content = get( # HTML elements reference - 'https://developer.mozilla.org/en-US/docs/Web/HTML/Element').content -soup = BeautifulSoup(content, features="lxml") + 'https://developer.mozilla.org/en-US/docs/Web/HTML/Element' +).content +soup = BeautifulSoup(content, features='lxml') tds = soup.select('td a code') counts = Counter(td.text.strip()[1:-1] for td in tds) names = set(counts) @@ -33,8 +39,9 @@ def parse(text: str) -> bytes: self_ending_wikitext = ('#<{}\n/>\n' * names_len).format(*names) start_only_wikitext = ('#<{}\n>\n' * names_len).format(*names) end_only_wikitext = ('#\n' * names_len).format(*names) -start_and_end_wikitext = ( - '#<{}\n/>\n' * names_len).format(*chain(*zip(names, names))) +start_and_end_wikitext = ('#<{}\n/>\n' * names_len).format( + *chain(*zip(names, names)) +) # https://www.mediawiki.org/wiki/API:Parsing_wikitext#Example_2:_Parse_a_section_of_a_page_and_fetch_its_table_data self_ending_html = parse(self_ending_wikitext) @@ -59,7 +66,9 @@ def parse(text: str) -> bytes: assert valid_start_and_end_names == valid_self_ending_names assert valid_self_ending_names - valid_start_only_names == { - 'section', 'source'} # note that both of them are extension tags + 'section', + 'source', +} # note that both of them are extension tags # len(valid_start_only_names) == 59 print(valid_start_only_names) @@ -73,4 +82,3 @@ def parse(text: str) -> bytes: # 'span', 'em', 'sup', 'div', 'h5', 'ol', 'bdi', 'kbd', 'dt', 'p', 'caption', # 'samp', 'strike', 'small', 'dl', 'i', 'tr'} # to be used in _config.py - diff --git a/dev/profiles/vs_mwpfh.py b/dev/profiles/vs_mwpfh.py index a0734502..8bb2d718 100644 --- a/dev/profiles/vs_mwpfh.py +++ b/dev/profiles/vs_mwpfh.py @@ -12,11 +12,7 @@ # # print('len(text):', len(text)) -repeat = partial( - repeat, - number=1, - repeat=10000, - globals=globals()) +repeat = partial(repeat, number=1, repeat=10000, globals=globals()) def print_min(marker, statement): @@ -24,20 +20,23 @@ def print_min(marker, statement): # Note that if the parse time is included, then wtp will be faster than mwp -p1 = wtp.parse("{{t|a|b|c|d}}") +p1 = wtp.parse('{{t|a|b|c|d}}') print_min( 'wtp,arg_val_assign', 'p1.templates[0].arguments', ) # 1.96000000000085e-05 -p2 = mwp.parse("{{t|a|b|c|d}}") +p2 = mwp.parse('{{t|a|b|c|d}}') print_min( 'mwp,arg_val_assign', 'p2.filter_templates()[0].params', ) # 9.199999999986996e-06 -assert p2.filter_templates()[0].params[3].name == p1.templates[0].arguments[3].name +assert ( + p2.filter_templates()[0].params[3].name + == p1.templates[0].arguments[3].name +) profiler = cProfile.Profile() diff --git a/docs/conf.py b/docs/conf.py index bc59bf2c..7021a2c6 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -38,7 +38,8 @@ extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.doctest', - 'sphinx.ext.viewcode'] + 'sphinx.ext.viewcode', +] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -68,7 +69,7 @@ open( join(repo_dir, 'wikitextparser', '__init__.py'), encoding='utf8' ).read(), - MULTILINE + MULTILINE, ).group(1) # The full version, including alpha/beta/rc tags. release = version @@ -134,15 +135,12 @@ # The paper size ('letterpaper' or 'a4paper'). # # 'papersize': 'letterpaper', - # The font size ('10pt', '11pt' or '12pt'). # # 'pointsize': '10pt', - # Additional stuff for the LaTeX preamble. # # 'preamble': '', - # Latex figure (float) alignment # # 'figure_align': 'htbp', @@ -151,11 +149,15 @@ # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). -latex_documents = [( - master_doc, 'wikitextparser.tex', 'wikitextparser Documentation', - '', # author_texescaped_str - 'manual', -)] +latex_documents = [ + ( + master_doc, + 'wikitextparser.tex', + 'wikitextparser Documentation', + '', # author_texescaped_str + 'manual', + ) +] # -- Options for manual page output --------------------------------------- @@ -163,8 +165,7 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - (master_doc, 'wikitextparser', 'wikitextparser Documentation', - [author], 1) + (master_doc, 'wikitextparser', 'wikitextparser Documentation', [author], 1) ] @@ -174,9 +175,15 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'wikitextparser', 'wikitextparser Documentation', - author, 'wikitextparser', 'One line description of project.', - 'Miscellaneous'), + ( + master_doc, + 'wikitextparser', + 'wikitextparser Documentation', + author, + 'wikitextparser', + 'One line description of project.', + 'Miscellaneous', + ), ] # If true, “(C) Copyright …” is shown in the HTML footer. Default is True. diff --git a/pyproject.toml b/pyproject.toml index 7c69402f..2bc2219b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,7 +56,7 @@ namespaces = false [tool.setuptools.dynamic.version] attr = "wikitextparser.__version__" -[tool.isort] -profile = "black" -line_length = 79 -combine_as_imports = true +[tool.ruff] +format.quote-style = 'single' +line-length = 79 +isort.combine-as-imports = true diff --git a/tests/test_argument.py b/tests/test_argument.py index 2a37d246..646b4e2e 100644 --- a/tests/test_argument.py +++ b/tests/test_argument.py @@ -63,9 +63,9 @@ def test_value_after_convertion_of_positional_to_keywordk(): def test_name_of_positionals(): - assert \ - ['1', '2', '3'] == \ - [a.name for a in parse('{{t|a|b|c}}').templates[0].arguments] + assert ['1', '2', '3'] == [ + a.name for a in parse('{{t|a|b|c}}').templates[0].arguments + ] def test_dont_confuse_subspan_equal_with_keyword_arg_equal(): @@ -78,7 +78,7 @@ def test_dont_confuse_subspan_equal_with_keyword_arg_equal(): def test_setting_positionality(): - a = Argument("|1=v") + a = Argument('|1=v') a.positional = False assert '|1=v' == a.string a.positional = True @@ -103,7 +103,7 @@ def test_section_not_keyword_arg(): assert (a.name, a.value) == ('', '=1==\n') # Todo: Prevents forming a template! # a = Argument('|\n==1==') - # assert + # assert # (a.name == a.value), ('1', '\n==1==') diff --git a/tests/test_cell.py b/tests/test_cell.py index eef75885..9c979c53 100644 --- a/tests/test_cell.py +++ b/tests/test_cell.py @@ -1,4 +1,4 @@ -from wikitextparser import parse +from wikitextparser import parse # noinspection PyProtectedMember from wikitextparser._table import Cell, Table @@ -7,7 +7,7 @@ def test_value(): c = Cell('\n| a ') assert ' a ' == c.value - assert repr(c) == 'Cell(\'\\n| a \')' + assert repr(c) == "Cell('\\n| a ')" assert c.attrs == {} # Use _cached_attrs assert c.attrs == {} diff --git a/tests/test_comment_bold_italic.py b/tests/test_comment_bold_italic.py index 5ceac90c..2f7eaa38 100644 --- a/tests/test_comment_bold_italic.py +++ b/tests/test_comment_bold_italic.py @@ -1,4 +1,4 @@ -from wikitextparser import Bold, Comment, Italic +from wikitextparser import Bold, Comment, Italic def test_comment(): @@ -16,7 +16,7 @@ def test_bold(): def test_italic(): assert Italic("''i").text == 'i' assert Italic("'''''i'''''").text == "'''i'''" - assert Italic("''i''").text == "i" + assert Italic("''i''").text == 'i' assert Italic("''i'''").text == "i'" # searching "''' ''i'''" for italics gives "''i'''", but it has not end assert Italic("''i'''", end_token=False).text == "i'''" @@ -47,7 +47,12 @@ def test_sub_italics(): def test_ref_text(): # 61 - assert Bold("'''\n", ).text == '\n' + assert ( + Bold( + "'''\n", + ).text + == '\n' + ) def test_close_only_comment(): diff --git a/tests/test_externallink.py b/tests/test_externallink.py index 5131007c..f525d6a1 100644 --- a/tests/test_externallink.py +++ b/tests/test_externallink.py @@ -1,4 +1,4 @@ -from wikitextparser import ExternalLink +from wikitextparser import ExternalLink def test_externallinks(): @@ -6,15 +6,18 @@ def test_externallinks(): def test_repr(): - assert repr(ExternalLink('HTTP://mediawiki.org')) == \ - "ExternalLink('HTTP://mediawiki.org')" + assert ( + repr(ExternalLink('HTTP://mediawiki.org')) + == "ExternalLink('HTTP://mediawiki.org')" + ) def test_numberedmailto_change_none_to_empty(): s = ( '[mailto:' 'info@example.org?Subject=URL%20Encoded%20Subject&body=' - 'Body%20Textinfo]') + 'Body%20Textinfo]' + ) el = ExternalLink(s) assert s[1:-1] == el.url assert el.text is None diff --git a/tests/test_parameter.py b/tests/test_parameter.py index b45692ae..d76cc54f 100644 --- a/tests/test_parameter.py +++ b/tests/test_parameter.py @@ -1,4 +1,4 @@ -from pytest import warns +from pytest import warns from wikitextparser import Parameter diff --git a/tests/test_parser_function.py b/tests/test_parser_function.py index a23e3b3d..cd274ca7 100644 --- a/tests/test_parser_function.py +++ b/tests/test_parser_function.py @@ -1,4 +1,4 @@ -from pytest import mark +from pytest import mark from wikitextparser import ParserFunction, WikiText @@ -7,8 +7,10 @@ def test_parser_function(): - assert repr(ParserFunction('{{#if:a|{{#if:b|c}}}}').parser_functions[0]) \ + assert ( + repr(ParserFunction('{{#if:a|{{#if:b|c}}}}').parser_functions[0]) == "ParserFunction('{{#if:b|c}}')" + ) def test_args_containing_braces(): @@ -16,16 +18,16 @@ def test_args_containing_braces(): def test_repr(): - assert repr(ParserFunction('{{#if:a|b}}')) ==\ - "ParserFunction('{{#if:a|b}}')" + assert ( + repr(ParserFunction('{{#if:a|b}}')) == "ParserFunction('{{#if:a|b}}')" + ) def test_name_and_args(): f = ParserFunction('{{ #if: test | true | false }}') assert ' #if' == f.name args = f.arguments - assert [': test ', '| true ', '| false '] ==\ - [a.string for a in args] + assert [': test ', '| true ', '| false '] == [a.string for a in args] assert args[0].name == '1' assert args[2].name == '3' @@ -46,12 +48,12 @@ def test_pipes_inside_params_or_templates(): def test_strip_empty_wikilink(): - pf = ParserFunction("{{ #if: test | [[|Alt]] }}") + pf = ParserFunction('{{ #if: test | [[|Alt]] }}') assert 2 == len(pf.arguments) def test_default_parser_function_without_hash_sign(): - assert 1 == len(WikiText("{{formatnum:text|R}}").parser_functions) + assert 1 == len(WikiText('{{formatnum:text|R}}').parser_functions) @mark.xfail @@ -60,15 +62,15 @@ def test_parser_function_alias_without_hash_sign(): See: //translatewiki.net/wiki/MediaWiki:Sp-translate-data-MagicWords/fa """ - assert 1 == len(WikiText("{{آرایش‌عدد:text|R}}").parser_functions) + assert 1 == len(WikiText('{{آرایش‌عدد:text|R}}').parser_functions) def test_argument_with_existing_span(): """Test when the span is already in type_to_spans.""" - pf = WikiText("{{formatnum:text}}").parser_functions[0] + pf = WikiText('{{formatnum:text}}').parser_functions[0] assert pf.arguments[0].value == 'text' assert pf.arguments[0].value == 'text' def test_tag_containing_pipe(): - assert len(ParserFunction("{{text|abc}}").arguments) == 1 + assert len(ParserFunction('{{text|abc}}').arguments) == 1 diff --git a/tests/test_section.py b/tests/test_section.py index be8c1bfe..dd175f04 100644 --- a/tests/test_section.py +++ b/tests/test_section.py @@ -1,4 +1,4 @@ -from pytest import mark +from pytest import mark from wikitextparser import Section diff --git a/tests/test_spans.py b/tests/test_spans.py index b4cfbb82..12a63ddb 100644 --- a/tests/test_spans.py +++ b/tests/test_spans.py @@ -1,4 +1,4 @@ -from typing import Dict, List +from typing import Dict, List from pytest import mark @@ -153,7 +153,7 @@ def test_unicode_parameters(): # noinspection PyProtectedMember def test_image_containing_wikilink(): (a, b, _, _), (c, d, _, _), (e, f, _, _) = parse( - "[[File:xyz.jpg|thumb|1px|txt1 [[wikilink1]] txt2 " "[[Wikilink2]].]]" + '[[File:xyz.jpg|thumb|1px|txt1 [[wikilink1]] txt2 ' '[[Wikilink2]].]]' )._type_to_spans['WikiLink'] assert a == 0 assert b == 65 @@ -175,7 +175,7 @@ def test_extracting_sections(): assert ( "[Section('\\n'), Section('== 1 ==\\n'), " "Section('== 2 ==\\n=== 2.1 ===\\n==== 2.1.1 ====\\n" - "===== 2.1.1.1 =====\\n=== 2.2 ===\\n=== 2.3 ===\\n" + '===== 2.1.1.1 =====\\n=== 2.2 ===\\n=== 2.3 ===\\n' "==== 2.3.1 ====\\n2.3.1\\n'), Section('=== 2.1 ===\\n" "==== 2.1.1 ====\\n===== 2.1.1.1 =====\\n'), " "Section('==== 2.1.1 ====\\n===== 2.1.1.1 =====\\n'), " @@ -204,7 +204,7 @@ def test_section_title_may_contain_template_newline_etc(): def test_keyword_and_positional_args_removal(): - wt = WikiText("text{{t1|kw=a|1=|pa|kw2=a|pa2}}{{t2|a|1|1=}}text") + wt = WikiText('text{{t1|kw=a|1=|pa|kw2=a|pa2}}{{t2|a|1|1=}}text') t1, t2 = wt.templates t1_args = t1.arguments t2_args = t2.arguments @@ -226,7 +226,7 @@ def test_keyword_and_positional_args_removal(): del t1_args[1][:] t1_args = t1.arguments t2_args = t2.arguments - assert "text{{t1|1=|kw2=a|pa2}}{{t2|a|1|1=}}text" == wt.string + assert 'text{{t1|1=|kw2=a|pa2}}{{t2|a|1|1=}}text' == wt.string assert 'pa2' == t1_args[2].value assert '1' == t1_args[2].name assert 'a' == t2_args[0].value @@ -625,4 +625,7 @@ def test_invalid_reverse_pipe_trick(): def test_invalid_tag(): # 121 assert bpts( b'a' - )['ExtensionTag'] == [[35, 49], [49, 61]] + )['ExtensionTag'] == [ + [35, 49], + [49, 61], + ] diff --git a/tests/test_table.py b/tests/test_table.py index bfef0bce..c2421515 100644 --- a/tests/test_table.py +++ b/tests/test_table.py @@ -13,6 +13,7 @@ # Table.data + def test_each_row_on_a_newline(): assert Table( '{|\n' @@ -24,8 +25,12 @@ def test_each_row_on_a_newline(): '|-\n' '|Butter\n' '|Ice cream \n' - '|}').data() == [ - ['Orange', 'Apple'], ['Bread', 'Pie'], ['Butter', 'Ice cream']] + '|}' + ).data() == [ + ['Orange', 'Apple'], + ['Bread', 'Pie'], + ['Butter', 'Ice cream'], + ] def test_with_optional_rowseprator_on_first_row(): @@ -35,88 +40,94 @@ def test_with_optional_rowseprator_on_first_row(): ' | a | b\n' ' |-\n' ' | c\n' - '|}').data() == [['b'], ['c']] + '|}' + ).data() == [ + ['b'], + ['c'], + ] def test_all_rows_are_on_a_single_line(): assert Table( - '{|\n' - '|a||b||c\n' - '|-\n' - '|d||e||f\n' - '|-\n' - '|g||h||i\n' - '|}').data() == [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']] + '{|\n' '|a||b||c\n' '|-\n' '|d||e||f\n' '|-\n' '|g||h||i\n' '|}' + ).data() == [ + ['a', 'b', 'c'], + ['d', 'e', 'f'], + ['g', 'h', 'i'], + ] def test_extra_spaces_have_no_effect(): assert Table( '{|\n| Orange || Apple || more\n|-\n' '| Bread || Pie || more\n|-\n' - '| Butter || Ice cream || and more\n|}').data() == [ + '| Butter || Ice cream || and more\n|}' + ).data() == [ ['Orange', 'Apple', 'more'], ['Bread', 'Pie', 'more'], - ['Butter', 'Ice cream', 'and more']] + ['Butter', 'Ice cream', 'and more'], + ] def test_longer_text_and_only_rstrip(): assert Table( - '{|\n|multi\nline\ntext. \n\n2nd paragraph. \n|' - '\n* ulli1\n* ulli2\n* ulli3\n|}' - ).data() == [ - ['multi\nline\ntext. \n\n2nd paragraph.', - '\n* ulli1\n* ulli2\n* ulli3']] + '{|\n|multi\nline\ntext. \n\n2nd paragraph. \n|' + '\n* ulli1\n* ulli2\n* ulli3\n|}' + ).data() == [ + [ + 'multi\nline\ntext. \n\n2nd paragraph.', + '\n* ulli1\n* ulli2\n* ulli3', + ] + ] def test_strip_is_false(): - assert Table( - '{|class=wikitable\n| a || b \n|}' - ).data(strip=False) == [[' a ', ' b ']] + assert Table('{|class=wikitable\n| a || b \n|}').data(strip=False) == [ + [' a ', ' b '] + ] def test_doublepipe_multiline(): - assert Table( - '{|\n|| multi\nline\n||\n 1\n|}' - ).data() == [['multi\nline', '\n 1']] + assert Table('{|\n|| multi\nline\n||\n 1\n|}').data() == [ + ['multi\nline', '\n 1'] + ] def test_with_headers(): assert Table( '{|\n! style="text-align:left;"| Item\n! Amount\n! Cost\n|-\n' '|Orange\n|10\n|7.00\n|-\n|Bread\n|4\n|3.00\n|-\n' - '|Butter\n|1\n|5.00\n|-\n!Total\n|\n|15.00\n|}').data() == [ + '|Butter\n|1\n|5.00\n|-\n!Total\n|\n|15.00\n|}' + ).data() == [ ['Item', 'Amount', 'Cost'], ['Orange', '10', '7.00'], ['Bread', '4', '3.00'], ['Butter', '1', '5.00'], - ['Total', '', '15.00']] + ['Total', '', '15.00'], + ] def test_with_caption(): assert Table( '{|\n|+Food complements\n|-\n|Orange\n|Apple\n|-\n' - '|Bread\n|Pie\n|-\n|Butter\n|Ice cream \n|}').data() == [ - ['Orange', 'Apple'], ['Bread', 'Pie'], ['Butter', 'Ice cream']] + '|Bread\n|Pie\n|-\n|Butter\n|Ice cream \n|}' + ).data() == [ + ['Orange', 'Apple'], + ['Bread', 'Pie'], + ['Butter', 'Ice cream'], + ] def test_with_caption_attrs(): assert Table( - '{|class=wikitable\n' - '|+ sal | no\n' - '|a \n' - '|}' + '{|class=wikitable\n' '|+ sal | no\n' '|a \n' '|}' ).data() == [['a']] def test_second_caption_is_ignored(): assert Table( - '{|\n' - ' |+ c1\n' - ' |+ c2\n' - '|-\n' - '|1\n' - '|2\n' - '|}').data() == [['1', '2']] + '{|\n' ' |+ c1\n' ' |+ c2\n' '|-\n' '|1\n' '|2\n' '|}' + ).data() == [['1', '2']] def test_unneeded_newline_after_table_start(): @@ -124,13 +135,9 @@ def test_unneeded_newline_after_table_start(): def test_text_after_tablestart_is_not_actually_inside_the_table(): - assert Table( - '{|\n' - ' text\n' - '|-\n' - '|c1\n' - '|c2\n' - '|}').data() == [['c1', 'c2']] + assert Table('{|\n' ' text\n' '|-\n' '|c1\n' '|c2\n' '|}').data() == [ + ['c1', 'c2'] + ] def test_empty_table(): @@ -138,9 +145,7 @@ def test_empty_table(): def test_empty_table_comment_end(): - assert Table( - '{|class=wikitable\n' - '|}').data() == [] + assert Table('{|class=wikitable\n' '|}').data() == [] def test_empty_table_semi_caption_comment(): @@ -148,37 +153,37 @@ def test_empty_table_semi_caption_comment(): def test_empty_cell(): - assert Table( - '{|class=wikitable\n||a || || c\n|}').data() == [['a', '', 'c']] + assert Table('{|class=wikitable\n||a || || c\n|}').data() == [ + ['a', '', 'c'] + ] def test_pipe_as_text(): - assert Table( - '{|class=wikitable\n||a | || c\n|}').data() == [['a |', 'c']] + assert Table('{|class=wikitable\n||a | || c\n|}').data() == [['a |', 'c']] def test_meaningless_rowsep(): - assert Table( - '{|class=wikitable\n' - '||a || || c\n' - '|-\n' - '|}').data() == [['a', '', 'c']] + assert Table('{|class=wikitable\n' '||a || || c\n' '|-\n' '|}').data() == [ + ['a', '', 'c'] + ] def test_template_inside_table(): - assert Table('{|class=wikitable\n|-\n|{{text|a}}\n|}').data() ==\ - [['{{text|a}}']] + assert Table('{|class=wikitable\n|-\n|{{text|a}}\n|}').data() == [ + ['{{text|a}}'] + ] def test_only_pipes_can_seprate_attributes(): """According to the note at mw:Help:Tables#Table_headers.""" assert Table( '{|class=wikitable\n! style="text-align:left;"! ' - 'Item\n! Amount\n! Cost\n|}').data() == [ - ['style="text-align:left;"! Item', 'Amount', 'Cost']] + 'Item\n! Amount\n! Cost\n|}' + ).data() == [['style="text-align:left;"! Item', 'Amount', 'Cost']] assert Table( '{|class=wikitable\n! style="text-align:left;"| ' - 'Item\n! Amount\n! Cost\n|}').data() == [['Item', 'Amount', 'Cost']] + 'Item\n! Amount\n! Cost\n|}' + ).data() == [['Item', 'Amount', 'Cost']] def test_double_exclamation_marks_are_valid_on_header_rows(): @@ -210,8 +215,8 @@ def test_odd_case1(): '|+t [[w]]\n\n' 'text\n' '|c2\n' - '|}').data(span=False) == [ - ['h1', '+ h2'], ['+ h4'], ['!+ h6'], ['c1', 'c2']] + '|}' + ).data(span=False) == [['h1', '+ h2'], ['+ h4'], ['!+ h6'], ['c1', 'c2']] def test_colspan_and_rowspan_and_span_false(): @@ -222,7 +227,8 @@ def test_colspan_and_rowspan_and_span_false(): ).data(span=False) == [ ['11'], ['21', '22', '23', '24', '25'], - ['31', '32', '33', '34']] + ['31', '32', '33', '34'], + ] def test_colspan_and_rowspan_and_span_true(): @@ -233,7 +239,8 @@ def test_colspan_and_rowspan_and_span_true(): ).data(span=True) == [ ['11', '11', '11', '11', '11', '11'], ['21', '22', '23', '24', '25', '25'], - ['21', '31', '32', '32', '33', '34']] + ['21', '31', '32', '32', '33', '34'], + ] def test_inline_colspan_and_rowspan(): @@ -242,36 +249,36 @@ def test_inline_colspan_and_rowspan(): ' !a !! b !! c !! rowspan = 2 | d \n' ' |- \n' ' | e || colspan = "2"| f\n' - '|}').data(span=True) == [ - ['a', 'b', 'c', 'd'], - ['e', 'f', 'f', 'd']] + '|}' + ).data(span=True) == [['a', 'b', 'c', 'd'], ['e', 'f', 'f', 'd']] def test_growing_downward_growing_cells(): assert Table( - '{|class=wikitable\n' - '| a || rowspan=0 | b\n' - '|-\n' - '| c\n' - '|}').data(span=True) == [['a', 'b'], ['c', 'b']] + '{|class=wikitable\n' '| a || rowspan=0 | b\n' '|-\n' '| c\n' '|}' + ).data(span=True) == [ + ['a', 'b'], + ['c', 'b'], + ] def test_colspan_0(): assert Table( - '{|class=wikitable\n' - '| colspan=0 | a || b\n' - '|-\n' - '| c || d\n' - '|}').data(span=True) == [['a', 'b'], ['c', 'd']] + '{|class=wikitable\n' '| colspan=0 | a || b\n' '|-\n' '| c || d\n' '|}' + ).data(span=True) == [ + ['a', 'b'], + ['c', 'd'], + ] def test_ending_row_group(): assert Table( - '{|class=wikitable\n' - '| rowspan = 3 | a || b\n' - '|-\n' - '| c\n' - '|}').data(span=True) == [['a', 'b'], ['a', 'c'], ['a', None]] + '{|class=wikitable\n' '| rowspan = 3 | a || b\n' '|-\n' '| c\n' '|}' + ).data(span=True) == [ + ['a', 'b'], + ['a', 'c'], + ['a', None], + ] def test_ending_row_group_and_rowspan_0(): @@ -280,26 +287,29 @@ def test_ending_row_group_and_rowspan_0(): '| rowspan = 3 | a || rowspan = 0 | b || c\n' '|-\n' '| d\n' - '|}').data(span=True) == [ - ['a', 'b', 'c'], ['a', 'b', 'd'], ['a', 'b', None]] + '|}' + ).data(span=True) == [['a', 'b', 'c'], ['a', 'b', 'd'], ['a', 'b', None]] def test_row_data(): - assert Table( - '{|\n|a||b||c\n|-\n|d||e||f\n|-\n|g||h||i\n|}' - ).data(row=1) == ['d', 'e', 'f'] + assert Table('{|\n|a||b||c\n|-\n|d||e||f\n|-\n|g||h||i\n|}').data( + row=1 + ) == ['d', 'e', 'f'] def test_column_data(): - assert Table( - '{|\n|a||b||c\n|-\n|d||e||f\n|-\n|g||h||i\n|}' - ).data(column=1) == ['b', 'e', 'h'] + assert Table('{|\n|a||b||c\n|-\n|d||e||f\n|-\n|g||h||i\n|}').data( + column=1 + ) == ['b', 'e', 'h'] def test_column_and_row_data(): - assert Table( - '{|\n|a||b||c\n|-\n|d||e||f\n|-\n|g||h||i\n|}' - ).data(column=1, row=1) == 'e' + assert ( + Table('{|\n|a||b||c\n|-\n|d||e||f\n|-\n|g||h||i\n|}').data( + column=1, row=1 + ) + == 'e' + ) def test_header_attr_with_exclamation_mark(): @@ -310,36 +320,31 @@ def test_header_attr_with_exclamation_mark(): def test_nonheader_attr_with_exclamation_mark(): assert Table( - '{|class=wikitable\n' - '| 1 !! 1 ! 1 |||| 3 || a4 ! a4 | 4\n' - '|}').data() == [['1 !! 1 ! 1', '', '3', '4']] + '{|class=wikitable\n' '| 1 !! 1 ! 1 |||| 3 || a4 ! a4 | 4\n' '|}' + ).data() == [['1 !! 1 ! 1', '', '3', '4']] def test_single_exclamation_is_not_attribute_data_separator(): assert Table( - '{|class=wikitable\n' - '! 1 !! 2 ! 2 !!!! 4 || a5 ! a5 | 5\n' - '|}').data() == [['1', '2 ! 2', '', '4', '5']] + '{|class=wikitable\n' '! 1 !! 2 ! 2 !!!! 4 || a5 ! a5 | 5\n' '|}' + ).data() == [['1', '2 ! 2', '', '4', '5']] def test_newline_cell_attr_closure_cant_be_cell_sep(): - assert Table( - '{|class=wikitable\n' - '||||| 2 ! 2\n' - '|}').data() == [['', '', '2 ! 2']] + assert Table('{|class=wikitable\n' '||||| 2 ! 2\n' '|}').data() == [ + ['', '', '2 ! 2'] + ] def test_attr_delimiter_cant_be_adjacent_to_cell_delimiter(): """Couldn't find a logical explanation for MW's behaviour.""" - assert Table( - '{|class=wikitable\n' - '!a| !!b|c\n' - '|}').data() == [['', 'c']] + assert Table('{|class=wikitable\n' '!a| !!b|c\n' '|}').data() == [ + ['', 'c'] + ] # Remove one space and... - assert Table( - '{|class=wikitable\n' - '!a|!!b|c\n' - '|}').data() == [['a', 'b|c']] + assert Table('{|class=wikitable\n' '!a|!!b|c\n' '|}').data() == [ + ['a', 'b|c'] + ] def test_unicode_data(): @@ -348,11 +353,13 @@ def test_unicode_data(): '{|class=wikitable\n' '|align="center" rowspan="1"|A\u201D\n' '|align="center" rowspan="1"|B\n' - '|}').data() == [['A”', 'B']] + '|}' + ).data() == [['A”', 'B']] # Table.caption, Table.caption_attrs + def test_no_caption(): table = Table('{| class="wikitable"\n|a\n|+ ignore\n|}') assert table.caption is None @@ -376,7 +383,8 @@ def test_set_caption_attrs_before_cap(): def test_no_attrs_but_caption(): text = ( '{|\n|+Food complements\n|-\n|Orange\n|Apple\n|-' - '\n|Bread\n|Pie\n|-\n|Butter\n|Ice cream \n|}') + '\n|Bread\n|Pie\n|-\n|Butter\n|Ice cream \n|}' + ) table = Table(text) assert table.caption == 'Food complements' assert table.caption_attrs is None @@ -388,16 +396,19 @@ def test_attrs_and_caption(): table = Table( '{| class="wikitable"\n' '|+ style="caption-side:bottom; color:#e76700;"|' - '\'\'Food complements\'\'\n|-\n|Orange\n|Apple\n|-' - '\n|Bread\n|Pie\n|-\n|Butter\n|Ice cream \n|}') + "''Food complements''\n|-\n|Orange\n|Apple\n|-" + '\n|Bread\n|Pie\n|-\n|Butter\n|Ice cream \n|}' + ) assert table.caption == "''Food complements''" - assert table.caption_attrs == \ - ' style="caption-side:bottom; color:#e76700;"' + assert ( + table.caption_attrs == ' style="caption-side:bottom; color:#e76700;"' + ) def test_header_cell_starts_with_dash(): - assert Table('''{| class="wikitable"\n!-a\n!-b\n|}''').data() == \ - [['-a', '-b']] + assert Table("""{| class="wikitable"\n!-a\n!-b\n|}""").data() == [ + ['-a', '-b'] + ] # Table.table_attrs @@ -411,7 +422,7 @@ def test_multiline_table(): assert table.get_attr('s') == '' table.del_attr('s') table.set_attr('class', 'wikitable') - assert repr(table) == "Table('{| class=\"wikitable\"\\n|a\\n|}')" + assert repr(table) == 'Table(\'{| class="wikitable"\\n|a\\n|}\')' assert table.get_attr('class') == 'wikitable' table.set_attr('class', 'sortable') @@ -421,17 +432,22 @@ def test_multiline_table(): def test_attr_contains_template_newline_invalid_chars(): - assert WikiText( - ' {| class=wikitable |ب style="color: {{text| 1 =\n' - 'red}};"\n' - '| cell\n' - '|}\n' - ).tables[0].get_attr('style') == 'color: {{text| 1 =\nred}};' + assert ( + WikiText( + ' {| class=wikitable |ب style="color: {{text| 1 =\n' + 'red}};"\n' + '| cell\n' + '|}\n' + ) + .tables[0] + .get_attr('style') + == 'color: {{text| 1 =\nred}};' + ) def test_pipe_in_text(): table = Table('{|\n| colspan="2" | text | with pipe\n|}') - assert table.cells()[0][0].attrs == {"colspan": "2"} + assert table.cells()[0][0].attrs == {'colspan': '2'} # Table.cells @@ -445,7 +461,8 @@ def test_cell_extraction(): '|| 5\n' '! 6 !! a | 7\n' '!| 8 || 9\n' - '|}') + '|}' + ) cells = table.cells() assert len(cells) == 1 assert len(cells[0]) == 9 @@ -458,7 +475,8 @@ def test_cell_extraction(): '\n! 6 ', '!! a | 7', '\n!| 8 ', - '|| 9') + '|| 9', + ) for r in cells: for i, c in enumerate(r): assert c.string == cell_string[i] @@ -471,9 +489,13 @@ def test_cell_extraction(): def test_cell_spans(): - assert WikiText( - '{|class=wikitable\n| a \n|}' - ).tables[0].cells(row=0, column=0).value == ' a ' + assert ( + WikiText('{|class=wikitable\n| a \n|}') + .tables[0] + .cells(row=0, column=0) + .value + == ' a ' + ) def test_changing_cell_should_effect_the_table(): @@ -490,14 +512,14 @@ def test_changing_cell_should_effect_the_table(): def test_cell_span_false(): - assert len(Table( - '{|class=wikitable\n|a=b|c\n|}').cells(span=False)) == 1 + assert len(Table('{|class=wikitable\n|a=b|c\n|}').cells(span=False)) == 1 def test_get_get_tables(): - assert repr( - Table('{|\n|a\n|-\n{|\n|b\n|}\n|}').get_tables() - ) == "[Table('{|\\n|b\\n|}')]" + assert ( + repr(Table('{|\n|a\n|-\n{|\n|b\n|}\n|}').get_tables()) + == "[Table('{|\\n|b\\n|}')]" + ) def test_weird_colspan(): @@ -507,7 +529,8 @@ def test_weird_colspan(): '|-\n' '| colspan=" 2a2"| a\n' '|colspan="1.5"| b\n' - '|}').data() == [['1', '2', '3', '4'], ['a', 'a', 'b', None]] + '|}' + ).data() == [['1', '2', '3', '4'], ['a', 'a', 'b', None]] def test_caption_containing_piped_wikilink(): @@ -515,7 +538,7 @@ def test_caption_containing_piped_wikilink(): def test_caption_multiline(): - assert Table('{|\n|+a\nb\nc\n|}').caption == "a\nb\nc" + assert Table('{|\n|+a\nb\nc\n|}').caption == 'a\nb\nc' def test_caption_end(): @@ -527,41 +550,48 @@ def test_caption_end(): # # """ but only one caption is valid in HTML. Most browsers ignore the # second caption tag. wikitextparser only returns the first one. - assert Table('{|\n|+ caption|| second caption!\n|}').caption == " caption" - assert Table('{|\n|+style="color:red;"|caption\n|}').caption == "caption" - assert Table('{|\n|+caption ! caption\n|}').caption == "caption ! caption" - assert Table('{|\n|+caption !! caption\n! header\n|}').caption \ - == "caption !! caption" + assert Table('{|\n|+ caption|| second caption!\n|}').caption == ' caption' + assert Table('{|\n|+style="color:red;"|caption\n|}').caption == 'caption' + assert Table('{|\n|+caption ! caption\n|}').caption == 'caption ! caption' + assert ( + Table('{|\n|+caption !! caption\n! header\n|}').caption + == 'caption !! caption' + ) def test_caption_multiline_rows(): - assert Table('{|\n|+a\nb\nc\n|-\n|cell\n|}').caption == "a\nb\nc" + assert Table('{|\n|+a\nb\nc\n|-\n|cell\n|}').caption == 'a\nb\nc' def test_cell_header(): - assert Table('{|\n!1!!style="color:red;"|2\n|}').cells( - row=0, column=1).is_header is True + assert ( + Table('{|\n!1!!style="color:red;"|2\n|}') + .cells(row=0, column=1) + .is_header + is True + ) def test_not_cell_header(): - assert Table('{|\n!Header\n|Not a header\n|}').cells( - row=0, column=1).is_header is False + assert ( + Table('{|\n!Header\n|Not a header\n|}') + .cells(row=0, column=1) + .is_header + is False + ) def test_table_attr_span_false(): # 71 cell = Table('{|\n|colspan=2| Test1 \n|| Test 2 \n|| Test 3 \n|}').cells( - span=False)[0][0] + span=False + )[0][0] assert cell.attrs == {'colspan': '2'} def test_comment_line(): # 98 assert Table( - '{|class=wikitable' - '\n!a' - '\n|-' - '\n' - '\n|b' - '\n|}').data() == [['a'], ['b']] + '{|class=wikitable' '\n!a' '\n|-' '\n' '\n|b' '\n|}' + ).data() == [['a'], ['b']] def test_partially_invalid_table(): # 107 @@ -589,10 +619,7 @@ def test_row_attrs_getter(): # multiple attrs on a row assert Table( - '{|\n' - '|-style="color: red;" bgcolor=yellow"\n' - '| cell1\n' - '|}' + '{|\n' '|-style="color: red;" bgcolor=yellow"\n' '| cell1\n' '|}' ).row_attrs == [ {'style': 'color: red;', 'bgcolor': 'yellow'}, ] @@ -627,10 +654,7 @@ def test_row_attrs_containing_comment(): def test_row_attrs_containing_template(): assert Table( - '{|\n' - '|- style={{text|"color: red;"}}\n' - '| cell1\n' - '|}' + '{|\n' '|- style={{text|"color: red;"}}\n' '| cell1\n' '|}' ).row_attrs == [ {'style': '{{text|"color: red;"}}'}, ] diff --git a/tests/test_tag.py b/tests/test_tag.py index 290c4ca6..4ce134cd 100644 --- a/tests/test_tag.py +++ b/tests/test_tag.py @@ -55,7 +55,7 @@ def test_start_tag_patterns(): 'attr_value': b'body', 'attr_insert': b'', } - assert start_tag_finder(b"").capturesdict() == { + assert start_tag_finder(b'
').capturesdict() == { 'attr_name': [b'a1', b'a2'], 'start_tag': [b'
'], 'attr': [b' a1=v1', b' a2=v2'], @@ -116,7 +116,7 @@ def test_get_attr_value(): def test_set_attr_value(): - t = Tag('c') + t = Tag("c") t.set_attr('n1', 'v4') t.set_attr('n2', 'v5') assert t.string == 'c' diff --git a/tests/test_template.py b/tests/test_template.py index bdb7ee60..52e8860f 100644 --- a/tests/test_template.py +++ b/tests/test_template.py @@ -39,19 +39,19 @@ def test_name(): assert ( ' wrapper ' == Template( - "{{ wrapper | p1 | {{ cite | sp1 | dateformat = ymd}} }}" + '{{ wrapper | p1 | {{ cite | sp1 | dateformat = ymd}} }}' ).name ) def test_dont_remove_nonkeyword_argument(): - assert "{{t|a|a}}" == str(Template("{{t|a|a}}")) + assert '{{t|a|a}}' == str(Template('{{t|a|a}}')) def test_set_name(): - t = Template("{{t|a|a}}") + t = Template('{{t|a|a}}') t.name = ' u ' - assert "{{ u |a|a}}" == t.string + assert '{{ u |a|a}}' == t.string def test_normal_name(): @@ -70,7 +70,7 @@ def test_normal_name(): def test_keyword_and_positional_args(): - assert '1' == Template("{{t|kw=a|1=|pa|kw2=a|pa2}}").arguments[2].name + assert '1' == Template('{{t|kw=a|1=|pa|kw2=a|pa2}}').arguments[2].name def test_rm_first_of_dup_args(): @@ -84,7 +84,7 @@ def test_rm_first_of_dup_args(): t.rm_first_of_dup_args() assert s == str(t) # Don't remove duplicate subargs - s1 = "{{i| c = {{g}} |p={{t|h={{g}}}} |q={{t|h={{g}}}}}}" + s1 = '{{i| c = {{g}} |p={{t|h={{g}}}} |q={{t|h={{g}}}}}}' t = Template(s1) t.rm_first_of_dup_args() assert s1 == str(t) @@ -104,7 +104,7 @@ def test_rm_first_of_dup_args(): def test_rm_dup_args_safe(): # Don't remove duplicate positional args in different positions - s = "{{cite|{{t1}}|{{t1}}}}" + s = '{{cite|{{t1}}|{{t1}}}}' t = Template(s) t.rm_dup_args_safe() assert s == t.string @@ -127,9 +127,9 @@ def test_rm_dup_args_safe(): t.rm_dup_args_safe() assert '{{t| v |1=v}}' == t.string # Removing a positional argument affects the name of later ones. - t = Template("{{t|1=|||}}") + t = Template('{{t|1=|||}}') t.rm_dup_args_safe() - assert "{{t|||}}" == t.string + assert '{{t|||}}' == t.string # Triple duplicates t = Template('{{t|1=v|v|1=v}}') t.rm_dup_args_safe() @@ -194,7 +194,7 @@ def test_overwriting_on_a_string_causes_loss_of_spans(): def test_no_param_template_name(): - assert 'صعود' == Template("{{صعود}}").name + assert 'صعود' == Template('{{صعود}}').name def test_lists(): @@ -321,15 +321,15 @@ def test_parser_functions(): def test_setting_single_space_arg(): # 97 - t = Template("{{t|a= }}") + t = Template('{{t|a= }}') t.set_arg('a', 'v', preserve_spacing=True) - assert t.string == "{{t|a=v }}" + assert t.string == '{{t|a=v }}' def test_preserve_spacing_left_and_right(): - t = Template("{{t|a=\tx }}") + t = Template('{{t|a=\tx }}') t.set_arg('a', 'y', preserve_spacing=True) - assert t.string == "{{t|a=\ty }}" + assert t.string == '{{t|a=\ty }}' def test_invalid_normal_name(): # 105 diff --git a/tests/test_wikilink.py b/tests/test_wikilink.py index d5202a67..8a15eceb 100644 --- a/tests/test_wikilink.py +++ b/tests/test_wikilink.py @@ -197,7 +197,7 @@ def test_title_and_fragment_deleters(): def test_called_from_plaintext(): # 119 - w0, w1 = parse("[[0]] [[1]]").wikilinks + w0, w1 = parse('[[0]] [[1]]').wikilinks del w0[:] assert w1.plain_text() == '1' diff --git a/tests/test_wikilist.py b/tests/test_wikilist.py index b5836f1a..b23b076c 100644 --- a/tests/test_wikilist.py +++ b/tests/test_wikilist.py @@ -70,10 +70,10 @@ def test_subitems_for_the_second_item(): def test_link_in_definition_list(): - wl = WikiList("; https://github.com : definition", pattern=r'[:;]\s*') - assert wl.items == ["https://github.com ", " definition"] - wl = WikiList("; https://a.b : c https://d.e : f", pattern=r'[:;]\s*') - assert wl.items == ["https://a.b ", " c https://d.e : f"] + wl = WikiList('; https://github.com : definition', pattern=r'[:;]\s*') + assert wl.items == ['https://github.com ', ' definition'] + wl = WikiList('; https://a.b : c https://d.e : f', pattern=r'[:;]\s*') + assert wl.items == ['https://a.b ', ' c https://d.e : f'] def test_mixed_definition_lists(): @@ -97,9 +97,9 @@ def test_mixed_definition_lists(): def test_order_definition_lists(): - wl = WikiList("; Item 1 : definition 1\n", pattern=r'[:;]\s*') - assert wl.items == ["Item 1 ", " definition 1"] - assert wl.fullitems == ["; Item 1 : definition 1\n", ": definition 1"] + wl = WikiList('; Item 1 : definition 1\n', pattern=r'[:;]\s*') + assert wl.items == ['Item 1 ', ' definition 1'] + assert wl.fullitems == ['; Item 1 : definition 1\n', ': definition 1'] def test_travese_mixed_list_completely(): @@ -151,7 +151,7 @@ def test_cache_update(): def test_external_link_colon_shadow(): # 91 - assert parse("===abc===\n; https://github.com : definition\n").get_lists( + assert parse('===abc===\n; https://github.com : definition\n').get_lists( r'[:;]' )[0]._list_shadow == bytearray(b'; __________________ : definition\n') diff --git a/tests/wikitext/test_external_links.py b/tests/wikitext/test_external_links.py index d464d83f..792a438d 100644 --- a/tests/wikitext/test_external_links.py +++ b/tests/wikitext/test_external_links.py @@ -216,11 +216,11 @@ def test_external_link_in_pf_in_tl(): # 110 def test_ext_link_overwriting_template(): # 74 - p = parse("{{test}}") + p = parse('{{test}}') t = p.templates[0] # It is could be considered unintuitive for p.templates to still return # [Template('[https://link]')]. As it stands, the user who is overwriting # the template should keep track of such changes and skip edited templates # that have become invalid. - t.string = "[https://link]" - assert p.external_links[0].string == "[https://link]" + t.string = '[https://link]' + assert p.external_links[0].string == '[https://link]' diff --git a/tests/wikitext/test_get_bolds_and_italics.py b/tests/wikitext/test_get_bolds_and_italics.py index 0ef4d52d..47776ddc 100644 --- a/tests/wikitext/test_get_bolds_and_italics.py +++ b/tests/wikitext/test_get_bolds_and_italics.py @@ -15,24 +15,30 @@ def anb(s: str): anb("''i1'''s") anb("") ab( - "a'''" - "b'''d", - "'''b'''") + "a'''" "b'''d", + "'''b'''", + ) ab("'''b{{a|'''}}", "'''b{{a|'''}}") # ? ab("a'''b{{text|c|d}}e'''f", "'''b{{text|c|d}}e'''") ab("{{text|'''b'''}}", "'''b'''") ab("{{text|'''b}}", "'''b") # ? ab("[[a|'''b]] c", "'''b") ab("{{{PARAM|'''b}}} c", "'''b") # ? - assert repr(parse("'''b\na'''c").get_bolds()) ==\ - """[Bold("'''b"), Bold("'''c")]""" + assert ( + repr(parse("'''b\na'''c").get_bolds()) + == """[Bold("'''b"), Bold("'''c")]""" + ) ab("'''b'''", "'''b'''") ab("'''br'''c", "'''br'''") ab("'''''b'''i", "'''b'''") - assert repr(parse("'''br'''ca").get_bolds()) == \ - """[Bold("'''br'''ca"), Bold("'''c")]""" - assert repr(parse("'''br'''ca").get_bolds(False)) ==\ - """[Bold("'''br'''ca")]""" + assert ( + repr(parse("'''br'''ca").get_bolds()) + == """[Bold("'''br'''ca"), Bold("'''c")]""" + ) + assert ( + repr(parse("'''br'''ca").get_bolds(False)) + == """[Bold("'''br'''ca")]""" + ) ab("'''b{{{p|'''}}}", "'''b{{{p|'''}}}") # ? ab("'''a'''b", "'''a") anb("' ' ' a ' ' '") @@ -53,14 +59,15 @@ def ai(s: str, o: str, r: bool = True): ai("a'' ''' ib ''' ''c", "'' ''' ib ''' ''") ai("''i''", "''i''") ai( - "A" + 'A' "'''''" - "i" + 'i' "'''''" - "B", + 'B', "'''''" - "i" - "'''''") + 'i' + "'''''", + ) ai("''' ''i'''", "''i'''") @@ -71,7 +78,7 @@ def test_bold_italic_index_change(): b1.text = '1' assert p.string == "'''1''' ''i1'' '''b2'''" assert i1.string == "''i1''" - assert b2.text == "b2" + assert b2.text == 'b2' def test_do_not_return_duplicate_bolds_italics(): # 42 @@ -86,32 +93,32 @@ def test_multiline_italics(): def test_first_single_letter_word_condition_in_doquotes(): - b, = parse("'''a'' b'''c'' '''d''").get_bolds() + (b,) = parse("'''a'' b'''c'' '''d''").get_bolds() assert b.string == "'''a'' b'''c'' '''" def test_first_space_condition_in_doquotes_not_used(): - b, = parse("'''a'' '''b'' '''c''").get_bolds() + (b,) = parse("'''a'' '''b'' '''c''").get_bolds() assert b.string == "'''b'' '''" def test_first_space_condition_in_balanced_quotes_shadow(): - b, = parse("a '''b'' '''c'' '''d''").get_bolds() + (b,) = parse("a '''b'' '''c'' '''d''").get_bolds() assert b.string == "'''c'' '''" def test_ignore_head_apostrophes(): - b, = parse("''''''''a").get_italics() + (b,) = parse("''''''''a").get_italics() assert b.string == "'''''a" def test_bold_ends_4_apostrophes(): - b, = parse("''a'''b''''").get_bolds() + (b,) = parse("''a'''b''''").get_bolds() assert b.text == "b'" def test_single_bold_italic(): - i, = parse("'''''a").get_italics() + (i,) = parse("'''''a").get_italics() assert i.text == "'''a" @@ -130,8 +137,9 @@ def test_bold_italics_order(): def test_wikilinks_in_extension_tags_should_not_create_duplicates(): # 57 - assert len( - parse("\n[[a|''b'']]\n").get_bolds_and_italics()) == 1 + assert ( + len(parse("\n[[a|''b'']]\n").get_bolds_and_italics()) == 1 + ) def test_italic_end_token(): diff --git a/tests/wikitext/test_get_lists.py b/tests/wikitext/test_get_lists.py index dda346a2..0a86e30b 100644 --- a/tests/wikitext/test_get_lists.py +++ b/tests/wikitext/test_get_lists.py @@ -22,7 +22,7 @@ def test_multiline_tags(): def test_definition_list_with_external_link(): # 91 - assert parse("; http://a.b :d\n").get_lists()[0].items == [ + assert parse('; http://a.b :d\n').get_lists()[0].items == [ ' http://a.b ', 'd', ] diff --git a/tests/wikitext/test_get_tags.py b/tests/wikitext/test_get_tags.py index 68aa1967..35dd1a98 100644 --- a/tests/wikitext/test_get_tags.py +++ b/tests/wikitext/test_get_tags.py @@ -29,10 +29,14 @@ def test_same_nested_tags(): def test_tag_extension_by_name(): - assert parse('pictures').get_tags('gallery')[0]. \ - contents == "pictures" - assert parse('pictures').get_tags('gallery')[0]. \ - contents == "pictures" + assert ( + parse('pictures').get_tags('gallery')[0].contents + == 'pictures' + ) + assert ( + parse('pictures').get_tags('gallery')[0].contents + == 'pictures' + ) def test_self_closing(): @@ -45,12 +49,12 @@ def test_self_closing(): def test_start_only(): """Some elements' end tag may be omitted in certain conditions. - An li element’s end tag may be omitted if the li element is immediately - followed by another li element or if there is no more content in the - parent element. + An li element’s end tag may be omitted if the li element is immediately + followed by another li element or if there is no more content in the + parent element. - See: https://www.w3.org/TR/html51/syntax.html#optional-tags - """ + See: https://www.w3.org/TR/html51/syntax.html#optional-tags + """ parsed = parse('
  • ') tags = parsed.get_tags() assert tags[0].string == '
  • ' @@ -64,9 +68,7 @@ def test_inner_tag(): def test_extension_tags_are_not_lost_in_shadows(): - parsed = parse( - 'textcitation\n' - '') + parsed = parse('textcitation\n' '') ref, references = parsed.get_tags() ref.set_attr('name', 'z') assert ref.string == 'citation' @@ -83,10 +85,14 @@ def test_pre(): # 46 def test_section_tag_apparently_containing_another_section_tag_start(): # 58 - assert parse('
    ').get_tags( - 'section')[0].contents == '' + assert ( + parse('
    ') + .get_tags('section')[0] + .contents + == '' + ) def test_tags_in_wikilinks(): - b, = parse('[[a|a c]] d').get_tags('b') + (b,) = parse('[[a|a c]] d').get_tags('b') assert b.string == 'c]] d' diff --git a/tests/wikitext/test_pformat.py b/tests/wikitext/test_pformat.py index 6f4c3928..28e5d2a1 100644 --- a/tests/wikitext/test_pformat.py +++ b/tests/wikitext/test_pformat.py @@ -3,30 +3,34 @@ def test_template_with_multi_args(): wt = WikiText('{{a|b=b|c=c|d=d|e=e}}') - assert '{{a\n | b = b\n | c = c\n | d = d\n | e = e\n}}' == \ - wt.pformat() + assert ( + '{{a\n | b = b\n | c = c\n | d = d\n | e = e\n}}' + == wt.pformat() + ) def test_double_space_indent(): - s = "{{a|b=b|c=c|d=d|e=e}}" + s = '{{a|b=b|c=c|d=d|e=e}}' wt = WikiText(s) - assert '{{a\n | b = b\n | c = c\n | d = d\n | e = e\n}}' == \ - wt.pformat(' ') + assert '{{a\n | b = b\n | c = c\n | d = d\n | e = e\n}}' == wt.pformat( + ' ' + ) def test_remove_comments(): - assert '{{a\n | e = e\n}}' == \ - WikiText('{{a|e=e}}').pformat(' ', True) + assert '{{a\n | e = e\n}}' == WikiText( + '{{a|e=e}}' + ).pformat(' ', True) def test_first_arg_of_tag_is_whitespace_sensitive(): """The second argument of #tag is an exception. - See the last warning on [[mw:Help:Magic_words#Miscellaneous]]: - You must write {{#tag:tagname||attribute1=value1|attribute2=value2}} - to pass an empty content. No space is permitted in the area reserved - for content between the pipe characters || before attribute1. - """ + See the last warning on [[mw:Help:Magic_words#Miscellaneous]]: + You must write {{#tag:tagname||attribute1=value1|attribute2=value2}} + to pass an empty content. No space is permitted in the area reserved + for content between the pipe characters || before attribute1. + """ s = '{{#tag:ref||name="n1"}}' wt = WikiText(s) assert s == wt.pformat() @@ -43,58 +47,49 @@ def test_invoke(): def test_on_parserfunction(): - s = "{{#if:c|abcde = f| g=h}}" + s = '{{#if:c|abcde = f| g=h}}' wt = parse(s) assert ( - '{{#if:\n' - ' c\n' - ' | abcde = f\n' - ' | g=h\n' - '}}') == wt.pformat() + '{{#if:\n' ' c\n' ' | abcde = f\n' ' | g=h\n' '}}' + ) == wt.pformat() def test_parserfunction_with_no_pos_arg(): - s = "{{#switch:case|a|b}}" + s = '{{#switch:case|a|b}}' wt = parse(s) assert ( - '{{#switch:\n' - ' case\n' - ' | a\n' - ' | b\n' - '}}') == wt.pformat() + '{{#switch:\n' ' case\n' ' | a\n' ' | b\n' '}}' + ) == wt.pformat() def test_convert_positional_to_keyword_if_possible(): - assert '{{t\n | 1 = a\n | 2 = b\n | 3 = c\n}}' ==\ - parse('{{t|a|b|c}}').pformat() + assert ( + '{{t\n | 1 = a\n | 2 = b\n | 3 = c\n}}' + == parse('{{t|a|b|c}}').pformat() + ) def test_inconvertible_positionals(): """Otherwise the second positional arg will also be passed as 1. - Because of T24555 we can't use "" to preserve the - whitespace of positional arguments. On the other hand we can't just - convert the initial arguments to keyword and keep the rest as - positional, because that would produce duplicate args as stated above. + Because of T24555 we can't use "" to preserve the + whitespace of positional arguments. On the other hand we can't just + convert the initial arguments to keyword and keep the rest as + positional, because that would produce duplicate args as stated above. - What we *can* do is to either convert all the arguments to keyword - args if possible, or we should only convert the longest part of - the tail of arguments that is convertible. + What we *can* do is to either convert all the arguments to keyword + args if possible, or we should only convert the longest part of + the tail of arguments that is convertible. - Use to align positional arguments where necessary. + Use to align positional arguments where necessary. - """ - assert ( - '{{t\n' - ' |a| b }}') == parse('{{t|a| b }}').pformat() + """ + assert ('{{t\n' ' |a| b }}') == parse( + '{{t|a| b }}' + ).pformat() assert ( - '{{t\n' - ' | a | 2 = b\n' - ' | 3 = c\n' - '}}') == parse('{{t| a |b|c}}').pformat() + '{{t\n' ' | a | 2 = b\n' ' | 3 = c\n' '}}' + ) == parse('{{t| a |b|c}}').pformat() def test_commented_repformat(): @@ -105,21 +100,19 @@ def test_commented_repformat(): def test_dont_treat_parser_function_arguments_as_kwargs(): """The `=` is usually just a part of parameter value. - Another example: {{fullurl:Category:Top level|action=edit}}. - """ + Another example: {{fullurl:Category:Top level|action=edit}}. + """ assert ( '{{#if:\n' ' true\n' ' | text\n' - '}}') == parse( - '{{#if:true|text}}' - ).pformat() + '}}' + ) == parse('{{#if:true|text}}').pformat() def test_ignore_zwnj_for_alignment(): assert ( - '{{ا\n | نیم\u200cفاصله = ۱\n |' - ' بدون نیم فاصله = ۲\n}}' + '{{ا\n | نیم\u200cفاصله = ۱\n |' ' بدون نیم فاصله = ۲\n}}' ) == parse('{{ا|نیم‌فاصله=۱|بدون نیم فاصله=۲}}').pformat() @@ -128,18 +121,21 @@ def test_equal_sign_alignment(): '{{t\n' ' | long_argument_name = 1\n' ' | 2 = 2\n' - '}}') == parse('{{t|long_argument_name=1|2=2}}').pformat() + '}}' + ) == parse('{{t|long_argument_name=1|2=2}}').pformat() def test_arabic_ligature_lam_with_alef(): """'ل' + 'ا' creates a ligature with one character width. - Some terminal emulators do not support this but it's defined in - Courier New font which is the main (almost only) font used for - monospaced Persian texts on Windows. Also tested on Arabic Wikipedia. - """ - assert '{{ا\n | الف = ۱\n | لا = ۲\n}}' == \ - parse('{{ا|الف=۱|لا=۲}}').pformat() + Some terminal emulators do not support this but it's defined in + Courier New font which is the main (almost only) font used for + monospaced Persian texts on Windows. Also tested on Arabic Wikipedia. + """ + assert ( + '{{ا\n | الف = ۱\n | لا = ۲\n}}' + == parse('{{ا|الف=۱|لا=۲}}').pformat() + ) def test_pf_inside_t(): @@ -150,43 +146,32 @@ def test_pf_inside_t(): ' I\n' ' | I\n' ' }}\n' - '}}') == wt.pformat() + '}}' + ) == wt.pformat() def test_nested_pf_inside_tl(): wt = parse('{{t1|{{t2}}{{#pf:a}}}}') assert ( - '{{t1\n' - ' | 1 = {{t2}}{{#pf:\n' - ' a\n' - ' }}\n' - '}}') == wt.pformat() + '{{t1\n' ' | 1 = {{t2}}{{#pf:\n' ' a\n' ' }}\n' '}}' + ) == wt.pformat() def test_html_tag_equal(): wt = parse('{{#iferror:|yes|no}}') assert ( - '{{#iferror:\n' - ' \n' - ' | yes\n' - ' | no\n' - '}}') == wt.pformat() + '{{#iferror:\n' ' \n' ' | yes\n' ' | no\n' '}}' + ) == wt.pformat() def test_pformat_tl_directly(): - assert ( - '{{t\n' - ' | 1 = a\n' - '}}') == Template('{{t|a}}').pformat() + assert ('{{t\n' ' | 1 = a\n' '}}') == Template('{{t|a}}').pformat() def test_pformat_pf_directly(): assert ( - '{{#iferror:\n' - ' \n' - ' | yes\n' - ' | no\n' - '}}') == ParserFunction('{{#iferror:|yes|no}}').pformat() + '{{#iferror:\n' ' \n' ' | yes\n' ' | no\n' '}}' + ) == ParserFunction('{{#iferror:|yes|no}}').pformat() def test_function_inside_template(): @@ -199,7 +184,8 @@ def test_function_inside_template(): ' | yes\n' ' }}\n' ' | 2 = a2\n' - '}}') == p.pformat() + '}}' + ) == p.pformat() def test_parser_template_parser(): @@ -214,7 +200,8 @@ def test_parser_template_parser(): ' | c\n' ' }}\n' ' }}\n' - '}}') == p.pformat() + '}}' + ) == p.pformat() def test_pfromat_first_arg_of_functions(): @@ -225,62 +212,41 @@ def test_pfromat_first_arg_of_functions(): ' | y\n' ' | \n' ' }}\n' - '}}') == parse('{{#time:{{#if:1|y|}}}}').pformat() + '}}' + ) == parse('{{#time:{{#if:1|y|}}}}').pformat() def test_pformat_pf_whitespace(): - assert ( - '{{#if:\n' - ' a\n' - '}}') == parse('{{#if: a}}').pformat() - assert ( - '{{#if:\n' - ' a\n' - '}}') == parse('{{#if:a }}').pformat() - assert ( - '{{#if:\n' - ' a\n' - '}}') == parse('{{#if: a }}').pformat() - assert ( - '{{#if:\n' - ' a= b\n' - '}}') == parse('{{#if: a= b }}').pformat() - assert ( - '{{#if:\n' - ' a = b\n' - '}}') == parse('{{#if:a = b }}').pformat() + assert ('{{#if:\n' ' a\n' '}}') == parse('{{#if: a}}').pformat() + assert ('{{#if:\n' ' a\n' '}}') == parse('{{#if:a }}').pformat() + assert ('{{#if:\n' ' a\n' '}}') == parse('{{#if: a }}').pformat() + assert ('{{#if:\n' ' a= b\n' '}}') == parse('{{#if: a= b }}').pformat() + assert ('{{#if:\n' ' a = b\n' '}}') == parse('{{#if:a = b }}').pformat() def test_pformat_tl_whitespace(): assert '{{t}}' == parse('{{ t }}').pformat() - assert ( - '{{ {{t}} \n' - ' | a = b\n' - '}}') == parse('{{ {{t}}|a=b}}').pformat() + assert ('{{ {{t}} \n' ' | a = b\n' '}}') == parse( + '{{ {{t}}|a=b}}' + ).pformat() def test_zwnj_is_not_whitespace(): - assert ( - '{{#if:\n' - ' \u200c\n' - '}}') == parse('{{#if:\u200c}}').pformat() + assert ('{{#if:\n' ' \u200c\n' '}}') == parse( + '{{#if:\u200c}}' + ).pformat() def test_colon_in_tl_name(): - assert ( - '{{en:text\n' - ' |text}}') == parse('{{en:text|text}}').pformat() - assert ( - '{{en:text\n' - ' |1|2}}') == parse('{{en:text|1|2}}').pformat() - assert ( - '{{en:text\n' - ' |1| 2=v }}') == parse('{{en:text|1|2=v}}').pformat() + assert ('{{en:text\n' ' |text}}') == parse( + '{{en:text|text}}' + ).pformat() + assert ('{{en:text\n' ' |1|2}}') == parse( + '{{en:text|1|2}}' + ).pformat() + assert ('{{en:text\n' ' |1| 2=v }}') == parse( + '{{en:text|1|2=v}}' + ).pformat() def test_parser_function_with_an_empty_argument(): @@ -288,10 +254,9 @@ def test_parser_function_with_an_empty_argument(): The code could benefit from a little improvement. """ - assert ( - '{{#rel2abs:\n' - ' \n' - '}}') == parse('{{ #rel2abs: }}').pformat() + assert ('{{#rel2abs:\n' ' \n' '}}') == parse( + '{{ #rel2abs: }}' + ).pformat() def test_parser_function_with_no_args(): @@ -299,18 +264,14 @@ def test_parser_function_with_no_args(): def test_pf_one_kw_arg(): - assert ( - '{{#expr:\n' - ' 2 = 3\n' - '}}') == parse('{{#expr: 2 = 3}}').pformat() + assert ('{{#expr:\n' ' 2 = 3\n' '}}') == parse( + '{{#expr: 2 = 3}}' + ).pformat() def test_pformat_inner_template(): a, b, c = WikiText('{{a|{{b|{{c}}}}}}').templates - assert ( - '{{b\n' - ' | 1 = {{c}}\n' - '}}') == b.pformat() + assert ('{{b\n' ' | 1 = {{c}}\n' '}}') == b.pformat() def test_repformat(): @@ -325,16 +286,18 @@ def test_repformat(): def test_pformat_keep_separated(): """Test that `{{ {{t}} }}` is not converted to `{{{{t}}}}`. - `{{{{t}}}}` will be interpreted as a parameter with {} around it. + `{{{{t}}}}` will be interpreted as a parameter with {} around it. - """ + """ assert '{{ {{t}} }}' == WikiText('{{{{t}} }}').pformat() def test_last_arg_last_char_is_newline(): """Do not add comment_indent when it has no effect.""" - assert '{{text\n |{{#if:\n \n }}\n}}' == \ - WikiText('{{text|{{#if:}}\n}}').pformat() + assert ( + '{{text\n |{{#if:\n \n }}\n}}' + == WikiText('{{text|{{#if:}}\n}}').pformat() + ) assert ( '{{text\n' ' |{{text\n' @@ -343,7 +306,8 @@ def test_last_arg_last_char_is_newline(): ' }}\n' '}}\n' - '}}') == WikiText('{{text|{{text|{{#if:}}\n}}\n}}').pformat() + '}}' + ) == WikiText('{{text|{{text|{{#if:}}\n}}\n}}').pformat() assert ( '{{text\n' ' |{{text\n' @@ -351,15 +315,19 @@ def test_last_arg_last_char_is_newline(): ' \n' ' }}\n' ' }}\n' - '}}') == WikiText('{{text|{{text|{{#if:}}\n }}\n}}').pformat() - assert '{{text\n |a\n |b\n}}' == WikiText( - '{{text|a\n |b\n}}').pformat() - assert '{{text\n |a\n | 2 = b\n}}' == WikiText( - '{{text|a\n |2=b\n}}').pformat() + '}}' + ) == WikiText('{{text|{{text|{{#if:}}\n }}\n}}').pformat() + assert ( + '{{text\n |a\n |b\n}}' + == WikiText('{{text|a\n |b\n}}').pformat() + ) assert ( - '{{en:text\n' - ' | n=v\n' - '}}') == parse('{{en:text|n=v\n}}').pformat() + '{{text\n |a\n | 2 = b\n}}' + == WikiText('{{text|a\n |2=b\n}}').pformat() + ) + assert ('{{en:text\n' ' | n=v\n' '}}') == parse( + '{{en:text|n=v\n}}' + ).pformat() def test_no_error(): @@ -371,28 +339,30 @@ def test_no_error(): '\n }}{{t' '\n | 1 = ' '\n }}' - '\n}}') + '\n}}' + ) assert parse('{{{{#t2:{{{p1|}}}}}{{#t3:{{{p2|}}}\n}}}}\n').pformat() == ( '{{ {{#t2:' '\n {{{p1|}}}' '\n }}{{#t3:' '\n {{{p2|}}}' '\n }} }}' - '\n') + '\n' + ) def test_after_section_title_deletion(): # 100 - section = parse("= t =\nc").sections[1] + section = parse('= t =\nc').sections[1] del section.title assert section.pformat() == 'c' - section = parse("l\n= t =\nc").sections[1] + section = parse('l\n= t =\nc').sections[1] del section.title assert section.pformat() == 'c' def test_mutated_template(): - t = parse("{{t|a}}").templates[0] + t = parse('{{t|a}}').templates[0] a = t.arguments[0] a.string = '' assert t.pformat() == '{{t}}' diff --git a/tests/wikitext/test_plain_text.py b/tests/wikitext/test_plain_text.py index ebf7e546..9a8b4dc8 100644 --- a/tests/wikitext/test_plain_text.py +++ b/tests/wikitext/test_plain_text.py @@ -6,10 +6,10 @@ def ap(s, p): assert parse(s).plain_text() == p ap('[https://wikimedia.org/ wm]', 'wm') - ap("{{{a}}}", '') - ap("abc", 'abc') + ap('{{{a}}}', '') + ap('abc', 'abc') ap("''w''", 'w') # could be '' as well - ap("[[file:a.jpg|[[w]]]]", '') + ap('[[file:a.jpg|[[w]]]]', '') ap('abc', 'abc') # 39 ap('{{a}}b{{c}}', 'b') # 39 ap('t [[a|b]] t', 't b t') @@ -21,7 +21,7 @@ def ap(s, p): ap('{{#if:a|y|n}}', '') ap("'''b'''", 'b') ap("''i''", 'i') - ap("{{{1|a}}}", 'a') + ap('{{{1|a}}}', 'a') def test_plain_text_should_not_mutate(): # 40 @@ -32,7 +32,7 @@ def test_plain_text_should_not_mutate(): # 40 def test_remove_markup(): - assert remove_markup("''a'' {{b}} c '''d'''") == "a c d" + assert remove_markup("''a'' {{b}} c '''d'''") == 'a c d' def test_do_not_include_end_tag(): @@ -64,7 +64,7 @@ def test_plain_text_non_root_node(): def test_extract_unparsable_extension_tags_first(): # 90 assert ( parse( - "[[a|[b]]]" + '[[a|[b]]]' ).plain_text() == '[b]' ) @@ -138,7 +138,7 @@ def test_table(): ) -TABLE_WITH_ROW_AND_COL_SPANS = '''{| class="wikitable" +TABLE_WITH_ROW_AND_COL_SPANS = """{| class="wikitable" !colspan="6"|Shopping List |- |rowspan="2"|Bread & Butter @@ -151,7 +151,7 @@ def test_table(): |colspan="2"|Ice cream |Butter |Yogurt -|}''' +|}""" def test_none_in_table_data(): @@ -161,7 +161,7 @@ def test_none_in_table_data(): ) -TABLE_WITH_CAPTION = '''{| +TABLE_WITH_CAPTION = """{| |+Food complements |- |Orange @@ -172,7 +172,7 @@ def test_none_in_table_data(): |- |Butter |Ice cream -|}''' +|}""" def test_table_caption(): diff --git a/tests/wikitext/test_sections.py b/tests/wikitext/test_sections.py index c26b2565..939b2b68 100644 --- a/tests/wikitext/test_sections.py +++ b/tests/wikitext/test_sections.py @@ -32,13 +32,8 @@ def test_inserting_into_sections(): assert 'c\n== s0 ==\nc\n== s1 ==\nc\n' == wt.string s1.insert(len(wt.string), '=== s2 ===\nc\n') assert ( - 'c\n' - '== s0 ==\n' - 'c\n' - '== s1 ==\n' - 'c\n' - '=== s2 ===\n' - 'c\n') == wt.string + 'c\n' '== s0 ==\n' 'c\n' '== s1 ==\n' 'c\n' '=== s2 ===\n' 'c\n' + ) == wt.string s3 = wt.sections[3] assert '=== s2 ===\nc\n' == s3.string diff --git a/tests/wikitext/test_tables.py b/tests/wikitext/test_tables.py index 73e1842f..e792b8de 100644 --- a/tests/wikitext/test_tables.py +++ b/tests/wikitext/test_tables.py @@ -34,8 +34,10 @@ def test_two_tables(): def test_nested_tables(): - s = 'text1\n{|class=wikitable\n|a\n|\n' \ - '{|class=wikitable\n|b\n|}\n|}\ntext2' + s = ( + 'text1\n{|class=wikitable\n|a\n|\n' + '{|class=wikitable\n|b\n|}\n|}\ntext2' + ) p = parse(s) assert 1 == len(p.get_tables()) # non-recursive tables = p.tables # recursive @@ -82,23 +84,27 @@ def test_comments_between_indentation(): def test_comments_between_indentation_after_them(): - assert parse( - ':: {|class=wikitable\n|a\n|}' - ).tables[0].string == '{|class=wikitable\n|a\n|}' + assert ( + parse(':: {|class=wikitable\n|a\n|}') + .tables[0] + .string + == '{|class=wikitable\n|a\n|}' + ) def test_indentation_cannot_be_inside_nowiki(): """A very unusual case. It would be OK to have false positives here. - Also false positive for tables are pretty much harmless here. + Also false positive for tables are pretty much harmless here. - The same thing may happen for tables which start right after a - templates, parser functions, wiki links, comments, or - other extension tags. + The same thing may happen for tables which start right after a + templates, parser functions, wiki links, comments, or + other extension tags. - """ - assert len(parse( - ':{|class=wikitable\n|a\n|}').tables) == 0 + """ + assert ( + len(parse(':{|class=wikitable\n|a\n|}').tables) == 0 + ) def test_template_before_or_after_table(): @@ -136,32 +142,35 @@ def test_nested_tables_sorted(): '{| style="border: 2px solid black; background:red; float:right"\n' '| style="border: 2px solid darkgray;" | 4_R00\n' '|}\n' - '|}') + '|}' + ) p = parse(s) assert 1 == len(p.get_tables()) # non-recursive tables = p.tables assert tables == sorted(tables, key=attrgetter('_span_data')) t0 = tables[0] assert s == t0.string - assert t0.data(strip=False) == [[ - ' 0', - ' 1\n' - '{| style="border: 2px solid black; background: green;" ' - '\n' - '| style="border: 2px solid darkgray;" | 1_G00\n|-\n' - '| style="border: 2px solid darkgray;" | 1_G10\n' - '|}', - ' 2', - '\n{| style="border: 2px solid black; background: yellow"\n' - '| style="border: 2px solid darkgray;" | 3_Y00\n|}\n' - '{| style="border: 2px solid black; background: Orchid"\n' - '| style="border: 2px solid darkgray;" | 3_O00\n' - '| style="border: 2px solid darkgray;" | 3_O01\n|}', - '\n{| style="border: 2px solid black; background:blue; float:left"' - '\n| style="border: 2px solid darkgray;" | 4_B00\n|}\n' - '{| style="border: 2px solid black; background:red; float:right"\n' - '| style="border: 2px solid darkgray;" | 4_R00\n|}' - ]] + assert t0.data(strip=False) == [ + [ + ' 0', + ' 1\n' + '{| style="border: 2px solid black; background: green;" ' + '\n' + '| style="border: 2px solid darkgray;" | 1_G00\n|-\n' + '| style="border: 2px solid darkgray;" | 1_G10\n' + '|}', + ' 2', + '\n{| style="border: 2px solid black; background: yellow"\n' + '| style="border: 2px solid darkgray;" | 3_Y00\n|}\n' + '{| style="border: 2px solid black; background: Orchid"\n' + '| style="border: 2px solid darkgray;" | 3_O00\n' + '| style="border: 2px solid darkgray;" | 3_O01\n|}', + '\n{| style="border: 2px solid black; background:blue; float:left"' + '\n| style="border: 2px solid darkgray;" | 4_B00\n|}\n' + '{| style="border: 2px solid black; background:red; float:right"\n' + '| style="border: 2px solid darkgray;" | 4_R00\n|}', + ] + ] assert tables[3].data() == [['3_O00', '3_O01']] assert 5 == len(tables[0].tables) # noinspection PyProtectedMember @@ -177,5 +186,5 @@ def test_nested_tables_sorted(): def test_tables_in_parsable_tag_extensions(): # 85 - table, = parse('\n{|\n|}\n').tables + (table,) = parse('\n{|\n|}\n').tables assert table.span == (14, 19) diff --git a/tests/wikitext/test_wikitext.py b/tests/wikitext/test_wikitext.py index fb792f9b..d94a471f 100644 --- a/tests/wikitext/test_wikitext.py +++ b/tests/wikitext/test_wikitext.py @@ -224,12 +224,12 @@ def test_overwriting_or_extending_selfspan_will_cause_data_loss(): def test_template_inside_wikilink(): - assert 2 == len(WikiText("{{text | [[ A | {{text|b}} ]] }}").templates) + assert 2 == len(WikiText('{{text | [[ A | {{text|b}} ]] }}').templates) def test_wikilink_in_template(): # todo: merge with test_spans? - s = "{{text |[[A|}}]]}}" + s = '{{text |[[A|}}]]}}' ts = str(WikiText(s).templates[0]) assert s == ts assert s == str(WikiText('{{text |[[A|}}]]}}').templates[0]) @@ -241,30 +241,30 @@ def test_wikilink_containing_closing_braces_in_template(): def test_ignore_comments(): - s1 = "{{text |}}" + s1 = '{{text |}}' assert s1 == str(WikiText(s1).templates[0]) def test_ignore_nowiki(): - assert "{{text |}} A }}" == str( - WikiText("{{text |}} A }} B").templates[0] + assert '{{text |}} A }}' == str( + WikiText('{{text |}} A }} B').templates[0] ) def test_template_inside_extension_tags(): - s = "{{t}}" + s = '{{t}}' assert '{{t}}' == str(WikiText(s).templates[0]) def test_dont_parse_source_tag(): - assert 0 == len(WikiText("{{t}}").templates) + assert 0 == len(WikiText('{{t}}').templates) # WikiText.parser_functions def test_comment_in_parserfunction_name(): - assert 1 == len(WikiText("{{#if:|a}}").parser_functions) + assert 1 == len(WikiText('{{#if:|a}}').parser_functions) # WikiText.wikilinks @@ -272,8 +272,8 @@ def test_comment_in_parserfunction_name(): def test_wikilink_inside_parser_function(): assert ( - "[[u:{{{3}}}|{{{3}}}]]" - == WikiText("{{ #if: {{{3|}}} | [[u:{{{3}}}|{{{3}}}]] }}") + '[[u:{{{3}}}|{{{3}}}]]' + == WikiText('{{ #if: {{{3|}}} | [[u:{{{3}}}|{{{3}}}]] }}') .wikilinks[0] .string ) @@ -294,7 +294,7 @@ def test_wikilink_target_may_contain_newline(): def test_getting_comment(): assert ( - "\n\nc\n{{A}}\n" + '\n\nc\n{{A}}\n' == WikiText('1 2').comments[0].contents ) @@ -370,7 +370,7 @@ def test_dead_index(): def test_wikitext_string_set(): # 66 - parsed = parse("[[a]]") + parsed = parse('[[a]]') wikilink = parsed.wikilinks[0] wikilink.insert(0, 'b') assert wikilink.string == 'b[[a]]' diff --git a/wikitextparser/_argument.py b/wikitextparser/_argument.py index c6301602..9c881c1e 100644 --- a/wikitextparser/_argument.py +++ b/wikitextparser/_argument.py @@ -1,4 +1,4 @@ -from typing import Dict, List, MutableSequence, Optional, Union +from typing import Dict, List, MutableSequence, Optional, Union from regex import DOTALL, MULTILINE diff --git a/wikitextparser/_cell.py b/wikitextparser/_cell.py index 4f4cded9..5fd772db 100644 --- a/wikitextparser/_cell.py +++ b/wikitextparser/_cell.py @@ -1,4 +1,4 @@ -from typing import Dict, List, Match, MutableSequence, Union +from typing import Dict, List, Match, MutableSequence, Union from regex import DOTALL, VERBOSE diff --git a/wikitextparser/_comment_bold_italic.py b/wikitextparser/_comment_bold_italic.py index ec9af14b..b86f26a3 100644 --- a/wikitextparser/_comment_bold_italic.py +++ b/wikitextparser/_comment_bold_italic.py @@ -1,18 +1,18 @@ -from typing import Dict, List, MutableSequence, Optional, Union +from typing import Dict, List, MutableSequence, Optional, Union from regex import DOTALL, MULTILINE from ._wikitext import SubWikiText, rc COMMENT_PATTERN = r'|\Z)' -COMMA_COMMENT = "'(?>" + COMMENT_PATTERN + ")*+" -COMMENT_COMMA = "(?>" + COMMENT_PATTERN + ")*+'" +COMMA_COMMENT = "'(?>" + COMMENT_PATTERN + ')*+' +COMMENT_COMMA = '(?>' + COMMENT_PATTERN + ")*+'" BOLD_FULLMATCH = rc( - COMMA_COMMENT * 2 + "'(.*?)(?>'" + COMMENT_COMMA * 2 + "|$)", + COMMA_COMMENT * 2 + "'(.*?)(?>'" + COMMENT_COMMA * 2 + '|$)', MULTILINE | DOTALL, ).fullmatch ITALIC_FULLMATCH = rc( - COMMA_COMMENT + "'(.*?)(?>'" + COMMENT_COMMA + "|$)", DOTALL + COMMA_COMMENT + "'(.*?)(?>'" + COMMENT_COMMA + '|$)', DOTALL ).fullmatch ITALIC_NOEND_FULLMATCH = rc(COMMA_COMMENT + "'(.*)", DOTALL).fullmatch diff --git a/wikitextparser/_config.py b/wikitextparser/_config.py index 28dd9f54..7e549bf4 100644 --- a/wikitextparser/_config.py +++ b/wikitextparser/_config.py @@ -126,22 +126,97 @@ def regex_pattern(words: _Iterable[str]) -> bytes: # https://phabricator.wikimedia.org/source/mediawiki/browse/master/includes/DefaultSettings.php # See also: https://www.mediawiki.org/wiki/Help:Links#External_links _bare_external_link_schemes = { - 'bitcoin:', 'ftp://', 'ftps://', 'geo:', 'git://', 'gopher://', 'http://', - 'https://', 'irc://', 'ircs://', 'magnet:', 'mailto:', 'mms://', 'news:', - 'nntp://', 'redis://', 'sftp://', 'sip:', 'sips:', 'sms:', 'ssh://', - 'svn://', 'tel:', 'telnet://', 'urn:', 'worldwind://', 'xmpp:', # '//' + 'bitcoin:', + 'ftp://', + 'ftps://', + 'geo:', + 'git://', + 'gopher://', + 'http://', + 'https://', + 'irc://', + 'ircs://', + 'magnet:', + 'mailto:', + 'mms://', + 'news:', + 'nntp://', + 'redis://', + 'sftp://', + 'sip:', + 'sips:', + 'sms:', + 'ssh://', + 'svn://', + 'tel:', + 'telnet://', + 'urn:', + 'worldwind://', + 'xmpp:', # '//' } # generated using dev/html_tag_names.py _valid_html_tag_names = { - 's', 'ins', 'code', 'b', 'ol', 'i', 'h5', 'th', 'dt', 'td', - 'wbr', 'div', 'big', 'p', 'small', 'h4', 'tt', 'span', 'font', - 'ruby', 'h3', 'dfn', 'rb', 'li', 'h1', 'cite', 'dl', 'rtc', 'em', - 'q', 'h2', 'samp', 'strike', 'time', 'blockquote', 'bdi', 'del', - 'br', 'rp', 'hr', 'abbr', 'sub', 'u', 'kbd', 'table', 'rt', 'dd', - 'var', 'ul', 'tr', 'center', 'data', 'strong', 'mark', - 'h6', 'bdo', 'caption', 'sup'} -_HTML_TAG_NAME = regex_pattern(_valid_html_tag_names) + br'\b' + 's', + 'ins', + 'code', + 'b', + 'ol', + 'i', + 'h5', + 'th', + 'dt', + 'td', + 'wbr', + 'div', + 'big', + 'p', + 'small', + 'h4', + 'tt', + 'span', + 'font', + 'ruby', + 'h3', + 'dfn', + 'rb', + 'li', + 'h1', + 'cite', + 'dl', + 'rtc', + 'em', + 'q', + 'h2', + 'samp', + 'strike', + 'time', + 'blockquote', + 'bdi', + 'del', + 'br', + 'rp', + 'hr', + 'abbr', + 'sub', + 'u', + 'kbd', + 'table', + 'rt', + 'dd', + 'var', + 'ul', + 'tr', + 'center', + 'data', + 'strong', + 'mark', + 'h6', + 'bdo', + 'caption', + 'sup', +} +_HTML_TAG_NAME = regex_pattern(_valid_html_tag_names) + rb'\b' _parser_functions = { 'ARTICLEPAGENAME', diff --git a/wikitextparser/_externallink.py b/wikitextparser/_externallink.py index 58c9277a..facd75a6 100644 --- a/wikitextparser/_externallink.py +++ b/wikitextparser/_externallink.py @@ -1,4 +1,4 @@ -from typing import List, Optional +from typing import List, Optional from ._wikitext import BRACKET_EXTERNAL_LINK_URL, IGNORECASE, SubWikiText, rc diff --git a/wikitextparser/_parameter.py b/wikitextparser/_parameter.py index 8f6076fe..9f250859 100644 --- a/wikitextparser/_parameter.py +++ b/wikitextparser/_parameter.py @@ -1,4 +1,4 @@ -from typing import List, Optional +from typing import List, Optional from ._wikitext import WS, SubWikiText @@ -97,7 +97,7 @@ def append_default(self, new_default_name: str) -> None: len('{{{' + name + '|') : len( '{{{' + name + '|' + innermost_default ) - ] = ('{{{' + new_default_name + '|' + innermost_default + '}}}') + ] = '{{{' + new_default_name + '|' + innermost_default + '}}}' @property def parameters(self) -> List['Parameter']: diff --git a/wikitextparser/_section.py b/wikitextparser/_section.py index 064bebd9..55b011c6 100644 --- a/wikitextparser/_section.py +++ b/wikitextparser/_section.py @@ -1,4 +1,4 @@ -from typing import Optional +from typing import Optional from ._wikitext import SubWikiText, rc @@ -70,7 +70,7 @@ def title(self, value: str) -> None: if m is None: raise RuntimeError( "Can't set title for a lead section. " - "Try adding it to contents." + 'Try adding it to contents.' ) self[m.start(2) : m.end(2)] = value diff --git a/wikitextparser/_spans.py b/wikitextparser/_spans.py index b88771bd..1988dd2f 100644 --- a/wikitextparser/_spans.py +++ b/wikitextparser/_spans.py @@ -1,4 +1,4 @@ -"""Define the functions required for parsing wikitext into spans.""" +"""Define the functions required for parsing wikitext into spans.""" from functools import partial from typing import Callable, Dict, Optional @@ -27,7 +27,9 @@ rb'[\s\0]*+' rb'(?>' rb'\#[^{}\s:|]++' # parser function - rb'|' + regex_pattern(_parser_functions)[3:] + # ) + rb'|' + + regex_pattern(_parser_functions)[3:] # ) + + # should not have any arguments or the arg should start with a : rb'(?:' rb':(?>[^{}]*+|}(?!})|{(?!{))*+' @@ -93,8 +95,8 @@ ).finditer MARKUP = b''.maketrans(b"|[]'{}", b'_\2\3___') -BRACES_PIPE_NEWLINE = b''.maketrans(b"|{}\n", b'____') -BRACKETS = b''.maketrans(b"[]", b'__') +BRACES_PIPE_NEWLINE = b''.maketrans(b'|{}\n', b'____') +BRACKETS = b''.maketrans(b'[]', b'__') PARSABLE_TAG_EXTENSION_NAME = regex_pattern(_parsable_tag_extensions) UNPARSABLE_TAG_EXTENSION_NAME = regex_pattern(_unparsable_tag_extensions) @@ -169,7 +171,12 @@ # Ignore ambiguous ampersand for the sake of simplicity. ATTRS_PATTERN = ( rb'(?' - rb'[' + SPACE_CHARS + rb']*+(?>' + ATTR_NAME + ATTR_VAL + rb')' + rb'[' + + SPACE_CHARS + + rb']*+(?>' + + ATTR_NAME + + ATTR_VAL + + rb')' # See https://stackoverflow.com/a/3558200/2705757 for how HTML5 # treats self-closing marks. + rb'|[^>]++' @@ -316,9 +323,10 @@ def _parse_sub_spans( tls_append: Callable, wls_append: Callable, ) -> None: - start_and_end_tags = *HTML_START_TAG_FINDITER( - byte_array, start, end - ), *HTML_END_TAG_FINDITER(byte_array, start, end) + start_and_end_tags = ( + *HTML_START_TAG_FINDITER(byte_array, start, end), + *HTML_END_TAG_FINDITER(byte_array, start, end), + ) for match in start_and_end_tags: ms, me = match.span() byte_array[ms:me] = byte_array[ms:me].translate(BRACKETS) diff --git a/wikitextparser/_table.py b/wikitextparser/_table.py index 4d391b8c..38033fd8 100644 --- a/wikitextparser/_table.py +++ b/wikitextparser/_table.py @@ -1,4 +1,4 @@ -from bisect import insort_right +from bisect import insort_right from collections.abc import Mapping from typing import Any, Dict, List, Optional, Tuple, TypeVar, Union @@ -48,7 +48,7 @@ # Captions are optional and only one should be placed between table-start # and the first row. Others captions are not part of the table and will # be ignored. -FIRST_NON_CAPTION_LINE = rc(br'\n[\t \0]*+(\|(?!\+)|!)').search +FIRST_NON_CAPTION_LINE = rc(rb'\n[\t \0]*+(\|(?!\+)|!)').search def head_int(value): diff --git a/wikitextparser/_tag.py b/wikitextparser/_tag.py index 541f037c..87c74c8f 100644 --- a/wikitextparser/_tag.py +++ b/wikitextparser/_tag.py @@ -1,4 +1,4 @@ -"""Define the Tag class and tag-related regular expressions. +"""Define the Tag class and tag-related regular expressions. Unlike MediaWiki which has very strict HTML rules, regexes defined in this module don't follow those restrictions and allow finding @@ -28,18 +28,18 @@ # ).finditer # Note that the following regex won't check for nested tags TAG_FULLMATCH = rc( - rb''' - <(?[A-Za-z0-9]++)''' + rb""" + <(?[A-Za-z0-9]++)""" + ATTRS_PATTERN - + rb''' - [''' + + rb""" + [""" + SPACE_CHARS - + rb''']*+ + + rb"""]*+ (?> - >(?.*)''' + >(?.*)""" + END_TAG_PATTERN.replace(rb'{name}', rb'(?[A-Za-z0-9]++)') - + rb'''|> # only start; no end tag; could be self-closing - )''', + + rb"""|> # only start; no end tag; could be self-closing + )""", DOTALL | VERBOSE, ).fullmatch diff --git a/wikitextparser/_wikilink.py b/wikitextparser/_wikilink.py index 5224ea6d..d4c33ebf 100644 --- a/wikitextparser/_wikilink.py +++ b/wikitextparser/_wikilink.py @@ -1,4 +1,4 @@ -"""Define the WikiLink class.""" +"""Define the WikiLink class.""" from typing import List, Optional diff --git a/wikitextparser/_wikitext.py b/wikitextparser/_wikitext.py index ff819d5e..2e63446f 100644 --- a/wikitextparser/_wikitext.py +++ b/wikitextparser/_wikitext.py @@ -362,7 +362,8 @@ def __setitem__(self, key: Union[slice, int], value: str) -> None: self._insert_update(abs_start, len_change) elif len_change < 0: self._del_update( - rmstart=abs_stop + len_change, rmstop=abs_stop # new stop + rmstart=abs_stop + len_change, + rmstop=abs_stop, # new stop ) # old stop # Add the newly added spans contained in the value. type_to_spans = self._type_to_spans