wikitextparser 0.56.2__tar.gz → 0.56.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. wikitextparser-0.56.4/.vscode/settings.json +7 -0
  2. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/CHANGELOG.rst +10 -0
  3. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/PKG-INFO +3 -2
  4. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/docs/conf.py +1 -1
  5. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/pyproject.toml +19 -1
  6. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/wikitextparser/__init__.py +1 -1
  7. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/wikitextparser/_argument.py +14 -11
  8. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/wikitextparser/_cell.py +18 -17
  9. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/wikitextparser/_comment_bold_italic.py +19 -13
  10. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/wikitextparser/_config.py +1 -1
  11. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/wikitextparser/_externallink.py +5 -5
  12. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/wikitextparser/_parameter.py +4 -4
  13. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/wikitextparser/_parser_function.py +8 -6
  14. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/wikitextparser/_section.py +5 -3
  15. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/wikitextparser/_spans.py +10 -4
  16. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/wikitextparser/_table.py +98 -36
  17. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/wikitextparser/_tag.py +8 -6
  18. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/wikitextparser/_template.py +28 -27
  19. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/wikitextparser/_wikilink.py +8 -10
  20. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/wikitextparser/_wikilist.py +27 -26
  21. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/wikitextparser/_wikitext.py +131 -114
  22. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/.coveragerc +0 -0
  23. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/.github/workflows/tests.yml +0 -0
  24. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/.gitignore +0 -0
  25. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/.readthedocs.yaml +0 -0
  26. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/LICENSE.md +0 -0
  27. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/README.rst +0 -0
  28. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/docs/CHANGELOG.rst +0 -0
  29. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/docs/Makefile +0 -0
  30. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/docs/README.rst +0 -0
  31. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/docs/index.rst +0 -0
  32. {wikitextparser-0.56.2 → wikitextparser-0.56.4}/docs/make.bat +0 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "python.testing.pytestArgs": [
3
+ "tests"
4
+ ],
5
+ "python.testing.unittestEnabled": false,
6
+ "python.testing.pytestEnabled": true
7
+ }
@@ -1,3 +1,13 @@
1
+ v0.56.4 (2025-05-14)
2
+ --------------------
3
+ * Fixed a bug in detection of images in ``plain_text`` method. (#141)
4
+ * Improved typehints.
5
+
6
+ v0.56.3 (2024-10-18)
7
+ --------------------
8
+ * Fixed a bug in detecting HTML tags nested in wiki markup. (#140)
9
+ * Improved type hints.
10
+
1
11
  v0.56.2
2
12
  -------
3
13
  * Fixed a bug in ``external_links`` property where ``|`` was recognized as part of the link by mistake. (#139)
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: wikitextparser
3
- Version: 0.56.2
3
+ Version: 0.56.4
4
4
  Summary: A simple parsing tool for MediaWiki's wikitext markup.
5
5
  Keywords: MediaWiki,wikitext,parser
6
6
  Author-email: 5j9 <5j9@users.noreply.github.com>
@@ -9,6 +9,7 @@ Description-Content-Type: text/x-rst
9
9
  Classifier: Programming Language :: Python
10
10
  Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
11
11
  Classifier: Topic :: Text Processing
12
+ License-File: LICENSE.md
12
13
  Requires-Dist: regex >= 2022.9.11
13
14
  Requires-Dist: wcwidth
14
15
  Requires-Dist: coverage ; extra == "dev"
@@ -69,7 +69,7 @@ version = search(
69
69
  join(repo_dir, 'wikitextparser', '__init__.py'), encoding='utf8'
70
70
  ).read(),
71
71
  MULTILINE,
72
- ).group(1)
72
+ ).group(1) # type: ignore
73
73
  # The full version, including alpha/beta/rc tags.
74
74
  release = version
75
75
 
@@ -50,13 +50,31 @@ line-length = 79
50
50
  format.quote-style = 'single'
51
51
  lint.isort.combine-as-imports = true
52
52
  lint.extend-select = [
53
+ 'W605', # invalid-escape-sequence
54
+ 'FA', # flake8-future-annotations
53
55
  'I', # isort
54
56
  'UP', # pyupgrade
57
+ 'RUF', # Ruff-specific rules (RUF)
55
58
  ]
56
59
  lint.ignore = [
57
- 'UP027', # list comprehensions are faster than generator expressions
58
60
  'E721', # Do not compare types, use `isinstance()`
61
+ 'RUF001', # ambiguous-unicode-character-string
62
+ 'RUF002', # ambiguous-unicode-character-docstring
63
+ 'RUF003', # ambiguous-unicode-character-comment
59
64
  ]
60
65
 
61
66
  [tool.pytest.ini_options]
62
67
  addopts = '--quiet --tb=short'
68
+
69
+ [tool.pyright]
70
+ typeCheckingMode = 'standard'
71
+ reportDeprecated = "warning"
72
+ reportPropertyTypeMismatch = "warning"
73
+ reportUnnecessaryCast = "warning"
74
+ reportUnnecessaryContains = "warning"
75
+ reportUnnecessaryIsInstance = "warning"
76
+ reportUnnecessaryTypeIgnoreComment = true
77
+ reportInvalidStringEscapeSequence = false
78
+ reportConstantRedefinition = 'error'
79
+ reportTypeCommentUsage = 'warning'
80
+ reportUnnecessaryComparison = 'warning'
@@ -1,5 +1,5 @@
1
1
  # Scheme: [N!]N(.N)*[{a|b|rc}N][.postN][.devN]
2
- __version__ = '0.56.2'
2
+ __version__ = '0.56.4'
3
3
 
4
4
  from . import _wikitext
5
5
  from ._argument import Argument # noqa: F401
@@ -1,7 +1,10 @@
1
- from typing import Dict, List, MutableSequence, Optional, Union
1
+ from __future__ import annotations
2
2
 
3
- from regex import DOTALL, MULTILINE
3
+ from typing import MutableSequence
4
4
 
5
+ from regex import DOTALL, MULTILINE, Match
6
+
7
+ from ._spans import TypeToSpans
5
8
  from ._wikitext import SECTION_HEADING, SubWikiText, rc
6
9
 
7
10
  ARG_SHADOW_FULLMATCH = rc(
@@ -21,32 +24,32 @@ class Argument(SubWikiText):
21
24
  See https://www.mediawiki.org/wiki/Help:Templates for more information.
22
25
  """
23
26
 
24
- __slots__ = '_shadow_match_cache', '_parent'
27
+ __slots__ = '_parent', '_shadow_match_cache'
25
28
 
26
29
  def __init__(
27
30
  self,
28
- string: Union[str, MutableSequence[str]],
29
- _type_to_spans: Optional[Dict[str, List[List[int]]]] = None,
30
- _span: Optional[List[int]] = None,
31
- _type: Optional[Union[str, int]] = None,
32
- _parent: 'SubWikiTextWithArgs' = None,
31
+ string: str | MutableSequence[str],
32
+ _type_to_spans: TypeToSpans | None = None,
33
+ _span: list[int] | None = None,
34
+ _type: str | int | None = None,
35
+ _parent: SubWikiTextWithArgs | None = None,
33
36
  ):
34
37
  super().__init__(string, _type_to_spans, _span, _type)
35
38
  self._parent = _parent or self
36
39
  self._shadow_match_cache = None, None
37
40
 
38
41
  @property
39
- def _shadow_match(self):
42
+ def _shadow_match(self) -> Match[bytes]:
40
43
  cached_shadow_match, cache_string = self._shadow_match_cache
41
44
  self_string = str(self)
42
45
  if cache_string == self_string:
43
- return cached_shadow_match
46
+ return cached_shadow_match # type: ignore
44
47
  ss, se, _, _ = self._span_data
45
48
  parent = self._parent
46
49
  ps = parent._span_data[0]
47
50
  shadow_match = ARG_SHADOW_FULLMATCH(parent._shadow[ss - ps : se - ps])
48
51
  self._shadow_match_cache = shadow_match, self_string
49
- return shadow_match
52
+ return shadow_match # type: ignore
50
53
 
51
54
  @property
52
55
  def name(self) -> str:
@@ -1,8 +1,10 @@
1
- from typing import Dict, List, Match, MutableSequence, Union
1
+ from __future__ import annotations
2
2
 
3
- from regex import DOTALL, VERBOSE
3
+ from typing import MutableSequence
4
4
 
5
- from ._spans import ATTRS_MATCH
5
+ from regex import DOTALL, VERBOSE, Match
6
+
7
+ from ._spans import ATTRS_MATCH, TypeToSpans
6
8
  from ._tag import SubWikiTextWithAttrs
7
9
  from ._wikitext import rc
8
10
 
@@ -140,19 +142,18 @@ INLINE_NONHAEDER_CELL_MATCH = rc(
140
142
 
141
143
 
142
144
  class Cell(SubWikiTextWithAttrs):
143
- __slots__ = '_header', '_match_cache', '_attrs_match_cache'
145
+ __slots__ = '_attrs_match_cache', '_header', '_match_cache'
144
146
 
145
147
  def __init__(
146
148
  self,
147
- string: Union[str, MutableSequence[str]],
149
+ string: str | MutableSequence[str],
148
150
  header: bool = False,
149
- _type_to_spans: Dict[str, List[List[int]]] = None,
150
- _span: int = None,
151
- _type: int = None,
152
- _match: Match = None,
153
- _attrs_match: Match = None,
151
+ _type_to_spans: TypeToSpans | None = None,
152
+ _span: list | None = None,
153
+ _type: int | None = None,
154
+ _match: Match | None = None,
155
+ _attrs_match: Match | None = None,
154
156
  ) -> None:
155
- """Initialize the object."""
156
157
  super().__init__(string, _type_to_spans, _span, _type)
157
158
  self._header = header
158
159
  if _match:
@@ -175,7 +176,7 @@ class Cell(SubWikiTextWithAttrs):
175
176
  self._attrs_match_cache = self._match_cache = None, None
176
177
 
177
178
  @property
178
- def _match(self):
179
+ def _match(self) -> Match[bytes]:
179
180
  """Return the match object for the current tag. Cache the result.
180
181
 
181
182
  Be extra careful when using this property. The position of match
@@ -185,15 +186,15 @@ class Cell(SubWikiTextWithAttrs):
185
186
  cache_match, cache_string = self._match_cache
186
187
  string = self.string
187
188
  if cache_string == string:
188
- return cache_match
189
+ return cache_match # type: ignore
189
190
  shadow = self._shadow
190
191
  if shadow[0] == 10: # ord('\n')
191
- m = NEWLINE_CELL_MATCH(shadow)
192
+ m: Match[bytes] = NEWLINE_CELL_MATCH(shadow) # type: ignore
192
193
  self._header = m['sep'] == 33 # ord('!')
193
194
  elif self._header:
194
- m = INLINE_HAEDER_CELL_MATCH(shadow)
195
+ m = INLINE_HAEDER_CELL_MATCH(shadow) # type: ignore
195
196
  else:
196
- m = INLINE_NONHAEDER_CELL_MATCH(shadow)
197
+ m = INLINE_NONHAEDER_CELL_MATCH(shadow) # type: ignore
197
198
  self._match_cache = m, string
198
199
  self._attrs_match_cache = None, None
199
200
  return m
@@ -245,7 +246,7 @@ class Cell(SubWikiTextWithAttrs):
245
246
  attrs_start, attrs_end = cell_match.span('attrs')
246
247
  if attrs_start != -1:
247
248
  encoded_attr_name = attr_name.encode()
248
- attrs_m = ATTRS_MATCH(shadow, attrs_start, attrs_end)
249
+ attrs_m: Match[bytes] = ATTRS_MATCH(shadow, attrs_start, attrs_end) # type: ignore
249
250
  for i, n in enumerate(reversed(attrs_m.captures('attr_name'))):
250
251
  if n == encoded_attr_name:
251
252
  vs, ve = attrs_m.spans('attr_value')[-i - 1]
@@ -1,7 +1,10 @@
1
- from typing import Dict, List, MutableSequence, Optional, Tuple, Union
1
+ from __future__ import annotations
2
2
 
3
- from regex import DOTALL, MULTILINE
3
+ from typing import MutableSequence
4
4
 
5
+ from regex import DOTALL, MULTILINE, Match
6
+
7
+ from ._spans import TypeToSpans
5
8
  from ._wikitext import SubWikiText, rc
6
9
 
7
10
  COMMENT_PATTERN = r'<!--[\s\S]*?(?>-->|\Z)'
@@ -29,13 +32,16 @@ class Comment(SubWikiText):
29
32
  return s[4:]
30
33
 
31
34
  @property
32
- def comments(self) -> List['Comment']:
35
+ def comments(self) -> list[Comment]:
33
36
  return []
34
37
 
35
38
 
36
39
  class BoldItalic(SubWikiText):
37
40
  __slots__ = ()
38
41
 
42
+ @property
43
+ def _match(self) -> Match[str]: ...
44
+
39
45
  @property
40
46
  def text(self) -> str:
41
47
  """Return text value of self (without triple quotes)."""
@@ -49,7 +55,7 @@ class BoldItalic(SubWikiText):
49
55
  self[b:e] = s
50
56
 
51
57
  @property
52
- def _content_span(self) -> Tuple[int, int]:
58
+ def _content_span(self) -> tuple[int, int]:
53
59
  # noinspection PyUnresolvedReferences
54
60
  return self._match.span(1)
55
61
 
@@ -58,8 +64,8 @@ class Bold(BoldItalic):
58
64
  __slots__ = ()
59
65
 
60
66
  @property
61
- def _match(self):
62
- return BOLD_FULLMATCH(self.string)
67
+ def _match(self) -> Match[str]:
68
+ return BOLD_FULLMATCH(self.string) # type: ignore
63
69
 
64
70
 
65
71
  class Italic(BoldItalic):
@@ -67,10 +73,10 @@ class Italic(BoldItalic):
67
73
 
68
74
  def __init__(
69
75
  self,
70
- string: Union[str, MutableSequence[str]],
71
- _type_to_spans: Optional[Dict[str, List[List[int]]]] = None,
72
- _span: Optional[List[int]] = None,
73
- _type: Optional[Union[str, int]] = None,
76
+ string: str | MutableSequence[str],
77
+ _type_to_spans: TypeToSpans | None = None,
78
+ _span: list[int] | None = None,
79
+ _type: str | int | None = None,
74
80
  end_token: bool = True,
75
81
  ):
76
82
  """Initialize the Italic object.
@@ -82,7 +88,7 @@ class Italic(BoldItalic):
82
88
  self.end_token = end_token
83
89
 
84
90
  @property
85
- def _match(self):
91
+ def _match(self) -> Match[str]:
86
92
  if self.end_token:
87
- return ITALIC_FULLMATCH(self.string)
88
- return ITALIC_NOEND_FULLMATCH(self.string)
93
+ return ITALIC_FULLMATCH(self.string) # type: ignore
94
+ return ITALIC_NOEND_FULLMATCH(self.string) # type: ignore
@@ -14,7 +14,7 @@ def _plant_trie(strings: _Iterable[str]) -> dict:
14
14
  for string in strings:
15
15
  d = trie
16
16
  for char in string:
17
- d[char] = char in d and d[char] or {}
17
+ d[char] = (char in d and d[char]) or {}
18
18
  d = d[char]
19
19
  d[''] = None # EOS
20
20
  return trie
@@ -1,4 +1,4 @@
1
- from typing import List, Optional
1
+ from __future__ import annotations
2
2
 
3
3
  from ._wikitext import BRACKET_EXTERNAL_LINK_URL, IGNORECASE, SubWikiText, rc
4
4
 
@@ -17,7 +17,7 @@ class ExternalLink(SubWikiText):
17
17
  external links.
18
18
  """
19
19
  if self(0) == '[':
20
- return self(1, URL_MATCH(self._ext_link_shadow, 1).end())
20
+ return self(1, URL_MATCH(self._ext_link_shadow, 1).end()) # type: ignore
21
21
  return self.string
22
22
 
23
23
  @url.setter
@@ -28,7 +28,7 @@ class ExternalLink(SubWikiText):
28
28
  self[0 : len(self.url)] = newurl
29
29
 
30
30
  @property
31
- def text(self) -> Optional[str]:
31
+ def text(self) -> str | None:
32
32
  """The text part (the part after the url).
33
33
 
34
34
  getter: Return None if this is a bare link or has no associated text.
@@ -38,7 +38,7 @@ class ExternalLink(SubWikiText):
38
38
  """
39
39
  string = self.string
40
40
  if string[0] == '[':
41
- url_end = URL_MATCH(self._ext_link_shadow, 1).end()
41
+ url_end = URL_MATCH(self._ext_link_shadow, 1).end() # type: ignore
42
42
  end_char = string[url_end]
43
43
  if end_char == ']':
44
44
  return None
@@ -74,5 +74,5 @@ class ExternalLink(SubWikiText):
74
74
  return self(0) == '['
75
75
 
76
76
  @property
77
- def external_links(self) -> List['ExternalLink']:
77
+ def external_links(self) -> list[ExternalLink]:
78
78
  return []
@@ -1,4 +1,4 @@
1
- from typing import List, Optional, Tuple
1
+ from __future__ import annotations
2
2
 
3
3
  from ._wikitext import WS, SubWikiText
4
4
 
@@ -35,7 +35,7 @@ class Parameter(SubWikiText):
35
35
  return '|' if self._shadow.find(124) != -1 else ''
36
36
 
37
37
  @property
38
- def default(self) -> Optional[str]:
38
+ def default(self) -> str | None:
39
39
  """The default value of current parameter.
40
40
 
41
41
  getter: Return None if there is no default.
@@ -100,9 +100,9 @@ class Parameter(SubWikiText):
100
100
  ] = '{{{' + new_default_name + '|' + innermost_default + '}}}'
101
101
 
102
102
  @property
103
- def parameters(self) -> List['Parameter']:
103
+ def parameters(self) -> list[Parameter]:
104
104
  return super().parameters[1:]
105
105
 
106
106
  @property
107
- def _content_span(self) -> Tuple[int, int]:
107
+ def _content_span(self) -> tuple[int, int]:
108
108
  return 3, -3
@@ -1,5 +1,7 @@
1
+ from __future__ import annotations
2
+
1
3
  from bisect import insort
2
- from typing import Iterable, List, Tuple, Union
4
+ from typing import Iterable
3
5
 
4
6
  from ._argument import Argument
5
7
  from ._wikilist import WikiList
@@ -19,7 +21,7 @@ class SubWikiTextWithArgs(SubWikiText):
19
21
  _first_arg_sep = 0
20
22
 
21
23
  @property
22
- def _content_span(self) -> Tuple[int, int]:
24
+ def _content_span(self) -> tuple[int, int]:
23
25
  return 2, -2
24
26
 
25
27
  @property
@@ -32,7 +34,7 @@ class SubWikiTextWithArgs(SubWikiText):
32
34
  return self._nesting_level(('Template', 'ParserFunction'))
33
35
 
34
36
  @property
35
- def arguments(self) -> List[Argument]:
37
+ def arguments(self) -> list[Argument]:
36
38
  """Parse template content. Create self.name and self.arguments."""
37
39
  shadow = self._shadow
38
40
  split_spans = self._name_args_matcher(shadow, 2, -2).spans('arg')
@@ -65,8 +67,8 @@ class SubWikiTextWithArgs(SubWikiText):
65
67
  return arguments
66
68
 
67
69
  def get_lists(
68
- self, pattern: Union[str, Iterable[str]] = (r'\#', r'\*', '[:;]')
69
- ) -> List[WikiList]:
70
+ self, pattern: str | Iterable[str] = (r'\#', r'\*', '[:;]')
71
+ ) -> list[WikiList]:
70
72
  """Return the lists in all arguments.
71
73
 
72
74
  For performance reasons it is usually preferred to get a specific
@@ -103,5 +105,5 @@ class ParserFunction(SubWikiTextWithArgs):
103
105
  _first_arg_sep = 58
104
106
 
105
107
  @property
106
- def parser_functions(self) -> List['ParserFunction']:
108
+ def parser_functions(self) -> list[ParserFunction]:
107
109
  return super().parser_functions[1:]
@@ -1,4 +1,6 @@
1
- from typing import Optional
1
+ from __future__ import annotations
2
+
3
+ from regex import Match
2
4
 
3
5
  from ._wikitext import SubWikiText, rc
4
6
 
@@ -37,7 +39,7 @@ class Section(SubWikiText):
37
39
 
38
40
  @level.setter
39
41
  def level(self, value: int) -> None:
40
- m = self._header_match
42
+ m: Match[bytes] = self._header_match # type: ignore
41
43
  level_diff = len(m[1]) - value
42
44
  if level_diff == 0:
43
45
  return
@@ -50,7 +52,7 @@ class Section(SubWikiText):
50
52
  del self[m.end(2) : m.end(2) + level_diff]
51
53
 
52
54
  @property
53
- def title(self) -> Optional[str]:
55
+ def title(self) -> str | None:
54
56
  """The title of this section.
55
57
 
56
58
  getter: Return the title or None for lead sections or sections that
@@ -1,7 +1,9 @@
1
1
  """Define the functions required for parsing wikitext into spans."""
2
2
 
3
+ from __future__ import annotations
4
+
3
5
  from functools import partial
4
- from typing import Callable, Dict, Optional
6
+ from typing import Callable, Dict, List, Union
5
7
 
6
8
  from regex import DOTALL, IGNORECASE, REVERSE, Match, compile as rc
7
9
 
@@ -210,7 +212,11 @@ HTML_END_TAG_FINDITER = rc(
210
212
  ).finditer
211
213
 
212
214
 
213
- def parse_to_spans(byte_array: bytearray) -> Dict[str, list]:
215
+ # [stan_start: int, span_end: int, Match, byte_array]
216
+ TypeToSpans = Dict[Union[str, int], List[List]]
217
+
218
+
219
+ def parse_to_spans(byte_array: bytearray) -> TypeToSpans:
214
220
  """Calculate and set self._type_to_spans.
215
221
 
216
222
  Extracted spans will be removed from byte_array.
@@ -321,7 +327,7 @@ def extract_tag_extensions(
321
327
  def _parse_sub_spans(
322
328
  byte_array: bytearray,
323
329
  start: int,
324
- end: Optional[int],
330
+ end: int | None,
325
331
  pms_append: Callable,
326
332
  pfs_append: Callable,
327
333
  tls_append: Callable,
@@ -336,7 +342,7 @@ def _parse_sub_spans(
336
342
  byte_array[ms:me] = byte_array[ms:me].translate(BRACKETS)
337
343
  while True:
338
344
  while True:
339
- match: Optional[Match] = None
345
+ match: Match | None = None
340
346
  for match in WIKILINK_PARAM_FINDITER(byte_array, start, end):
341
347
  ms, me = match.span()
342
348
  if match[1] is None: