From d4f6bffd23dad852d03894db74e4e91e657df8ca Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Sat, 28 Jun 2025 16:44:59 -0400 Subject: [PATCH] Update type annotations and rerun ruff --- docs/conf.py | 4 +- pyproject.toml | 13 ++++ scripts/memtest.py | 12 ++-- src/mwparserfromhell/definitions.py | 4 +- src/mwparserfromhell/nodes/__init__.py | 6 +- src/mwparserfromhell/nodes/_base.py | 13 ++-- src/mwparserfromhell/nodes/argument.py | 18 ++--- src/mwparserfromhell/nodes/comment.py | 3 +- src/mwparserfromhell/nodes/external_link.py | 18 ++--- src/mwparserfromhell/nodes/extras/__init__.py | 4 +- src/mwparserfromhell/nodes/extras/attribute.py | 21 +++--- src/mwparserfromhell/nodes/extras/parameter.py | 13 ++-- src/mwparserfromhell/nodes/heading.py | 16 +++-- src/mwparserfromhell/nodes/html_entity.py | 30 ++++---- src/mwparserfromhell/nodes/tag.py | 52 +++++++------- src/mwparserfromhell/nodes/template.py | 64 +++++++++-------- src/mwparserfromhell/nodes/text.py | 5 +- src/mwparserfromhell/nodes/wikilink.py | 18 ++--- src/mwparserfromhell/parser/__init__.py | 4 +- src/mwparserfromhell/parser/builder.py | 7 +- src/mwparserfromhell/parser/contexts.py | 4 +- src/mwparserfromhell/parser/ctokenizer/common.h | 2 +- src/mwparserfromhell/parser/ctokenizer/contexts.h | 2 +- .../parser/ctokenizer/definitions.c | 2 +- .../parser/ctokenizer/definitions.h | 2 +- src/mwparserfromhell/parser/ctokenizer/tag_data.c | 2 +- src/mwparserfromhell/parser/ctokenizer/tag_data.h | 2 +- .../parser/ctokenizer/textbuffer.c | 2 +- .../parser/ctokenizer/textbuffer.h | 2 +- src/mwparserfromhell/parser/ctokenizer/tok_parse.c | 2 +- src/mwparserfromhell/parser/ctokenizer/tok_parse.h | 2 +- .../parser/ctokenizer/tok_support.c | 2 +- .../parser/ctokenizer/tok_support.h | 2 +- src/mwparserfromhell/parser/ctokenizer/tokenizer.c | 2 +- src/mwparserfromhell/parser/ctokenizer/tokenizer.h | 2 +- src/mwparserfromhell/parser/ctokenizer/tokens.c | 2 +- src/mwparserfromhell/parser/ctokenizer/tokens.h | 2 +- src/mwparserfromhell/parser/errors.py | 6 +- src/mwparserfromhell/parser/tokenizer.py | 12 ++-- src/mwparserfromhell/parser/tokens.py | 4 +- src/mwparserfromhell/smart_list/__init__.py | 4 +- src/mwparserfromhell/smart_list/list_proxy.py | 4 +- src/mwparserfromhell/smart_list/smart_list.py | 4 +- src/mwparserfromhell/smart_list/utils.py | 4 +- src/mwparserfromhell/string_mixin.py | 6 +- src/mwparserfromhell/utils.py | 2 +- src/mwparserfromhell/wikicode.py | 81 +++++++++++----------- tests/conftest.py | 4 +- tests/test_argument.py | 5 +- tests/test_attribute.py | 5 +- tests/test_builder.py | 7 +- tests/test_comment.py | 4 +- tests/test_docs.py | 6 +- tests/test_external_link.py | 5 +- tests/test_heading.py | 5 +- tests/test_html_entity.py | 4 +- tests/test_parameter.py | 5 +- tests/test_parser.py | 5 +- tests/test_smart_list.py | 4 +- tests/test_string_mixin.py | 4 +- tests/test_tag.py | 5 +- tests/test_template.py | 7 +- tests/test_text.py | 4 +- tests/test_tokenizer.py | 6 +- tests/test_tokens.py | 4 +- tests/test_utils.py | 5 +- tests/test_wikicode.py | 11 +-- tests/test_wikilink.py | 5 +- 68 files changed, 353 insertions(+), 245 deletions(-) create mode 100644 pyproject.toml diff --git a/docs/conf.py b/docs/conf.py index 4d01fdf..cae8fae 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- -# # mwparserfromhell documentation build configuration file, created by # sphinx-quickstart on Tue Aug 21 20:47:26 2012. # @@ -11,8 +9,8 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import sys import os +import sys # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..0fc845a --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,13 @@ +[tool.pyright] +pythonVersion = "3.9" +venvPath = "." +venv = ".venv" + +[tool.ruff] +target-version = "py39" + +[tool.ruff.lint] +extend-select = [ + "I", + "UP", +] diff --git a/scripts/memtest.py b/scripts/memtest.py index 56284f1..c3bb60f 100644 --- a/scripts/memtest.py +++ b/scripts/memtest.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -30,10 +30,12 @@ Actual memory leaks typically leak very large amounts of memory (megabytes) and scale with the number of loops. """ +from __future__ import annotations + +import sys from locale import LC_ALL, setlocale -from multiprocessing import Process, Pipe +from multiprocessing import Pipe, Process from os import listdir, path -import sys import psutil @@ -80,7 +82,7 @@ class MemoryTest: def _load(self): def load_file(filename): - with open(filename, "rU") as fp: + with open(filename) as fp: text = fp.read() name = path.split(filename)[1][: 0 - len(extension)] self._parse_file(name, text) @@ -109,7 +111,7 @@ class MemoryTest: tmpl = "{0}LEAKING{1}: {2:n} bytes, {3:.2%} inc ({4:n} bytes/loop)" sys.stdout.write(tmpl.format(Color.YELLOW, Color.RESET, d, p, bpt)) else: - sys.stdout.write("{}OK{}".format(Color.GREEN, Color.RESET)) + sys.stdout.write(f"{Color.GREEN}OK{Color.RESET}") def run(self): """Run the memory test suite.""" diff --git a/src/mwparserfromhell/definitions.py b/src/mwparserfromhell/definitions.py index 14c4ade..25c4787 100644 --- a/src/mwparserfromhell/definitions.py +++ b/src/mwparserfromhell/definitions.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,8 @@ When updating this file, please also update the the C tokenizer version: - mwparserfromhell/parser/ctokenizer/definitions.h """ +from __future__ import annotations + __all__ = [ "get_html_tag", "is_parsable", diff --git a/src/mwparserfromhell/nodes/__init__.py b/src/mwparserfromhell/nodes/__init__.py index 1b7badc..689fa92 100644 --- a/src/mwparserfromhell/nodes/__init__.py +++ b/src/mwparserfromhell/nodes/__init__.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -27,9 +27,10 @@ the name of a :class:`.Template` is a :class:`.Wikicode` object that can contain text or more templates. """ +from __future__ import annotations + from . import extras from ._base import Node -from .text import Text from .argument import Argument from .comment import Comment from .external_link import ExternalLink @@ -37,6 +38,7 @@ from .heading import Heading from .html_entity import HTMLEntity from .tag import Tag from .template import Template +from .text import Text from .wikilink import Wikilink __all__ = [ diff --git a/src/mwparserfromhell/nodes/_base.py b/src/mwparserfromhell/nodes/_base.py index 2fc24e5..18753b3 100644 --- a/src/mwparserfromhell/nodes/_base.py +++ b/src/mwparserfromhell/nodes/_base.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -18,7 +18,10 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -from typing import TYPE_CHECKING, Any, Generator, Optional, Callable +from __future__ import annotations + +from collections.abc import Generator +from typing import TYPE_CHECKING, Any, Callable from ..string_mixin import StringMixIn @@ -45,18 +48,18 @@ class Node(StringMixIn): def __str__(self) -> str: raise NotImplementedError() - def __children__(self) -> Generator["Wikicode", None, None]: + def __children__(self) -> Generator[Wikicode, None, None]: return # pylint: disable=unreachable yield # pragma: no cover (this is a generator that yields nothing) - def __strip__(self, **kwargs: Any) -> Optional[str]: + def __strip__(self, **kwargs: Any) -> str | None: return None def __showtree__( self, write: Callable[[str], None], - get: Callable[["Wikicode"], None], + get: Callable[[Wikicode], None], mark: Callable[[], None], ) -> None: write(str(self)) diff --git a/src/mwparserfromhell/nodes/argument.py b/src/mwparserfromhell/nodes/argument.py index 80c9c01..7cf6e27 100644 --- a/src/mwparserfromhell/nodes/argument.py +++ b/src/mwparserfromhell/nodes/argument.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -18,11 +18,13 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +from __future__ import annotations -from typing import TYPE_CHECKING, Any, Generator, Optional, Callable +from collections.abc import Generator +from typing import TYPE_CHECKING, Any, Callable -from ._base import Node from ..utils import parse_anything +from ._base import Node if TYPE_CHECKING: from ..wikicode import Wikicode @@ -44,12 +46,12 @@ class Argument(Node): return start + "|" + str(self.default) + "}}}" return start + "}}}" - def __children__(self) -> Generator["Wikicode", None, None]: + def __children__(self) -> Generator[Wikicode, None, None]: yield self.name if self.default is not None: yield self.default - def __strip__(self, **kwargs: Any) -> Optional[str]: + def __strip__(self, **kwargs: Any) -> str | None: if self.default is not None: return self.default.strip_code(**kwargs) return None @@ -57,7 +59,7 @@ class Argument(Node): def __showtree__( self, write: Callable[[str], None], - get: Callable[["Wikicode"], None], + get: Callable[[Wikicode], None], mark: Callable[[], None], ) -> None: write("{{{") @@ -69,7 +71,7 @@ class Argument(Node): write("}}}") @property - def name(self) -> "Wikicode": + def name(self) -> Wikicode: """The name of the argument to substitute.""" return self._name @@ -78,7 +80,7 @@ class Argument(Node): self._name = parse_anything(value) @property - def default(self) -> Optional["Wikicode"]: + def default(self) -> Wikicode | None: """The default value to substitute if none is passed. This will be ``None`` if the argument wasn't defined with one. The diff --git a/src/mwparserfromhell/nodes/comment.py b/src/mwparserfromhell/nodes/comment.py index 2631efc..5afdebc 100644 --- a/src/mwparserfromhell/nodes/comment.py +++ b/src/mwparserfromhell/nodes/comment.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -18,6 +18,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +from __future__ import annotations from typing import Any diff --git a/src/mwparserfromhell/nodes/external_link.py b/src/mwparserfromhell/nodes/external_link.py index 696934e..b380d30 100644 --- a/src/mwparserfromhell/nodes/external_link.py +++ b/src/mwparserfromhell/nodes/external_link.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -18,11 +18,13 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +from __future__ import annotations -from typing import TYPE_CHECKING, Any, Optional, Generator, Callable +from collections.abc import Generator +from typing import TYPE_CHECKING, Any, Callable -from ._base import Node from ..utils import parse_anything +from ._base import Node if TYPE_CHECKING: from ..wikicode import Wikicode @@ -55,12 +57,12 @@ class ExternalLink(Node): return "[" + str(self.url) + "]" return str(self.url) - def __children__(self) -> Generator["Wikicode", None, None]: + def __children__(self) -> Generator[Wikicode, None, None]: yield self.url if self.title is not None: yield self.title - def __strip__(self, **kwargs: Any) -> Optional[str]: + def __strip__(self, **kwargs: Any) -> str | None: if self.brackets: if self.title: return self.title.strip_code(**kwargs) @@ -70,7 +72,7 @@ class ExternalLink(Node): def __showtree__( self, write: Callable[[str], None], - get: Callable[["Wikicode"], None], + get: Callable[[Wikicode], None], mark: Callable[[], None], ) -> None: if self.brackets: @@ -82,7 +84,7 @@ class ExternalLink(Node): write("]") @property - def url(self) -> "Wikicode": + def url(self) -> Wikicode: """The URL of the link target, as a :class:`.Wikicode` object.""" return self._url @@ -94,7 +96,7 @@ class ExternalLink(Node): self._url = parse_anything(value, contexts.EXT_LINK_URI) @property - def title(self) -> Optional["Wikicode"]: + def title(self) -> Wikicode | None: """The link title (if given), as a :class:`.Wikicode` object.""" return self._title diff --git a/src/mwparserfromhell/nodes/extras/__init__.py b/src/mwparserfromhell/nodes/extras/__init__.py index 4bfe4c8..769a085 100644 --- a/src/mwparserfromhell/nodes/extras/__init__.py +++ b/src/mwparserfromhell/nodes/extras/__init__.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2016 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -23,6 +23,8 @@ This package contains objects used by :class:`.Node`\\ s, but that are not nodes themselves. This includes template parameters and HTML tag attributes. """ +from __future__ import annotations + __all__ = [ "Attribute", "Parameter", diff --git a/src/mwparserfromhell/nodes/extras/attribute.py b/src/mwparserfromhell/nodes/extras/attribute.py index 98f8c13..91514da 100644 --- a/src/mwparserfromhell/nodes/extras/attribute.py +++ b/src/mwparserfromhell/nodes/extras/attribute.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -18,8 +18,9 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +from __future__ import annotations -from typing import TYPE_CHECKING, Any, Optional +from typing import TYPE_CHECKING, Any from ...string_mixin import StringMixIn from ...utils import parse_anything @@ -42,7 +43,7 @@ class Attribute(StringMixIn): self, name: Any, value: Any = None, - quotes: Optional[str] = '"', + quotes: str | None = '"', pad_first: str = " ", pad_before_eq: str = "", pad_after_eq: str = "", @@ -54,7 +55,7 @@ class Attribute(StringMixIn): self._pad_after_eq: str self.name = name - self._quotes: Optional[str] = None + self._quotes: str | None = None self.value = value self.quotes = quotes self.pad_first = pad_first @@ -71,7 +72,7 @@ class Attribute(StringMixIn): return result @staticmethod - def _value_needs_quotes(value: "Wikicode") -> Optional[str]: + def _value_needs_quotes(value: Wikicode) -> str | None: """Return valid quotes for the given value, or None if unneeded.""" if not value: return None @@ -95,15 +96,15 @@ class Attribute(StringMixIn): setattr(self, attr, value) @staticmethod - def coerce_quotes(quotes: Any) -> Optional[str]: + def coerce_quotes(quotes: Any) -> str | None: """Coerce a quote type into an acceptable value, or raise an error.""" coerced_quotes = str(quotes) if quotes else None if coerced_quotes not in [None, '"', "'"]: - raise ValueError("{!r} is not a valid quote type".format(quotes)) + raise ValueError(f"{quotes!r} is not a valid quote type") return coerced_quotes @property - def name(self) -> "Wikicode": + def name(self) -> Wikicode: """The name of the attribute as a :class:`.Wikicode` object.""" return self._name @@ -112,7 +113,7 @@ class Attribute(StringMixIn): self._name = parse_anything(value) @property - def value(self) -> Optional["Wikicode"]: + def value(self) -> Wikicode | None: """The value of the attribute as a :class:`.Wikicode` object.""" return self._value @@ -128,7 +129,7 @@ class Attribute(StringMixIn): self._value = code @property - def quotes(self) -> Optional[str]: + def quotes(self) -> str | None: """How to enclose the attribute value. ``"``, ``'``, or ``None``.""" return self._quotes diff --git a/src/mwparserfromhell/nodes/extras/parameter.py b/src/mwparserfromhell/nodes/extras/parameter.py index dac3ecc..d14f559 100644 --- a/src/mwparserfromhell/nodes/extras/parameter.py +++ b/src/mwparserfromhell/nodes/extras/parameter.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -18,9 +18,10 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -from typing import TYPE_CHECKING, Any, Union +from __future__ import annotations import re +from typing import TYPE_CHECKING, Any from ...string_mixin import StringMixIn from ...utils import parse_anything @@ -52,12 +53,12 @@ class Parameter(StringMixIn): return str(self.value) @staticmethod - def can_hide_key(key: Any) -> Union[re.Match, None]: + def can_hide_key(key: Any) -> re.Match | None: """Return whether or not the given key can be hidden.""" return re.match(r"[1-9][0-9]*$", str(key).strip()) @property - def name(self) -> "Wikicode": + def name(self) -> Wikicode: """The name of the parameter as a :class:`.Wikicode` object.""" return self._name @@ -66,7 +67,7 @@ class Parameter(StringMixIn): self._name = parse_anything(newval) @property - def value(self) -> "Wikicode": + def value(self) -> Wikicode: """The value of the parameter as a :class:`.Wikicode` object.""" return self._value @@ -83,5 +84,5 @@ class Parameter(StringMixIn): def showkey(self, newval: Any) -> None: newval = bool(newval) if not newval and not self.can_hide_key(self.name): - raise ValueError("parameter key {!r} cannot be hidden".format(self.name)) + raise ValueError(f"parameter key {self.name!r} cannot be hidden") self._showkey = newval diff --git a/src/mwparserfromhell/nodes/heading.py b/src/mwparserfromhell/nodes/heading.py index 9c1b122..b3b0a1c 100644 --- a/src/mwparserfromhell/nodes/heading.py +++ b/src/mwparserfromhell/nodes/heading.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -18,11 +18,13 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +from __future__ import annotations -from typing import TYPE_CHECKING, Any, Generator, Callable, Optional +from collections.abc import Generator +from typing import TYPE_CHECKING, Any, Callable -from ._base import Node from ..utils import parse_anything +from ._base import Node if TYPE_CHECKING: from ..wikicode import Wikicode @@ -39,16 +41,16 @@ class Heading(Node): def __str__(self) -> str: return ("=" * self.level) + str(self.title) + ("=" * self.level) - def __children__(self) -> Generator["Wikicode", None, None]: + def __children__(self) -> Generator[Wikicode, None, None]: yield self.title - def __strip__(self, **kwargs: Any) -> Optional[str]: + def __strip__(self, **kwargs: Any) -> str | None: return self.title.strip_code(**kwargs) def __showtree__( self, write: Callable[[str], None], - get: Callable[["Wikicode"], None], + get: Callable[[Wikicode], None], mark: Callable[[], None], ) -> None: write("=" * self.level) @@ -56,7 +58,7 @@ class Heading(Node): write("=" * self.level) @property - def title(self) -> "Wikicode": + def title(self) -> Wikicode: """The title of the heading, as a :class:`.Wikicode` object.""" return self._title diff --git a/src/mwparserfromhell/nodes/html_entity.py b/src/mwparserfromhell/nodes/html_entity.py index 2e77120..de51262 100644 --- a/src/mwparserfromhell/nodes/html_entity.py +++ b/src/mwparserfromhell/nodes/html_entity.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -18,8 +18,10 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -from typing import Any, Optional +from __future__ import annotations + import html.entities as htmlentities +from typing import Any from ._base import Node @@ -32,7 +34,7 @@ class HTMLEntity(Node): def __init__( self, value: Any, - named: Optional[bool] = None, + named: bool | None = None, hexadecimal: bool = False, hex_char: str = "x", ): @@ -58,12 +60,12 @@ class HTMLEntity(Node): def __str__(self) -> str: if self.named: - return "&{};".format(self.value) + return f"&{self.value};" if self.hexadecimal: - return "&#{}{};".format(self.hex_char, self.value) - return "&#{};".format(self.value) + return f"&#{self.hex_char}{self.value};" + return f"&#{self.value};" - def __strip__(self, **kwargs: Any) -> Optional[str]: + def __strip__(self, **kwargs: Any) -> str | None: if kwargs.get("normalize"): return self.normalize() return str(self) @@ -84,23 +86,21 @@ class HTMLEntity(Node): except ValueError: if newval not in htmlentities.entitydefs: raise ValueError( - "entity value {!r} is not a valid name".format(newval) + f"entity value {newval!r} is not a valid name" ) from None self._named = True self._hexadecimal = False else: if intval < 0 or intval > 0x10FFFF: raise ValueError( - "entity value 0x{:x} is not in range(0x110000)".format(intval) + f"entity value 0x{intval:x} is not in range(0x110000)" ) from None self._named = False self._hexadecimal = True else: test = int(newval, 16 if self.hexadecimal else 10) if test < 0 or test > 0x10FFFF: - raise ValueError( - "entity value {} is not in range(0x110000)".format(test) - ) + raise ValueError(f"entity value {test} is not in range(0x110000)") self._named = False self._value = newval @@ -118,16 +118,14 @@ class HTMLEntity(Node): def named(self, newval: bool) -> None: newval = bool(newval) if newval and self.value not in htmlentities.entitydefs: - raise ValueError("entity value {!r} is not a valid name".format(self.value)) + raise ValueError(f"entity value {self.value!r} is not a valid name") if not newval: try: int(self.value, 16) except ValueError as exc: raise ValueError( - "current entity value {!r} is not a valid Unicode codepoint".format( - self.value - ) + f"current entity value {self.value!r} is not a valid Unicode codepoint" ) from exc self._named = newval diff --git a/src/mwparserfromhell/nodes/tag.py b/src/mwparserfromhell/nodes/tag.py index 2c1e92b..a314847 100644 --- a/src/mwparserfromhell/nodes/tag.py +++ b/src/mwparserfromhell/nodes/tag.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -18,13 +18,15 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +from __future__ import annotations -from typing import TYPE_CHECKING, Any, Callable, Optional, List, Generator +from collections.abc import Generator +from typing import TYPE_CHECKING, Any, Callable -from ._base import Node -from .extras import Attribute from ..definitions import is_visible from ..utils import parse_anything +from ._base import Node +from .extras import Attribute if TYPE_CHECKING: from ..wikicode import Wikicode @@ -39,19 +41,19 @@ class Tag(Node): self, tag: Any, contents: Any = None, - attrs: Optional[List[Attribute]] = None, - wiki_markup: Optional[str] = None, + attrs: list[Attribute] | None = None, + wiki_markup: str | None = None, self_closing: bool = False, invalid: bool = False, implicit: bool = False, padding: str = "", - closing_tag: Optional["Wikicode"] = None, - wiki_style_separator: Optional[str] = None, - closing_wiki_markup: Optional[str] = None, + closing_tag: Wikicode | None = None, + wiki_style_separator: str | None = None, + closing_wiki_markup: str | None = None, ): super().__init__() - self._attrs: List[Attribute] - self._closing_wiki_markup: Optional[str] + self._attrs: list[Attribute] + self._closing_wiki_markup: str | None self.tag = tag self.contents = contents @@ -98,7 +100,7 @@ class Tag(Node): result += "" return result - def __children__(self) -> Generator["Wikicode", None, None]: + def __children__(self) -> Generator[Wikicode, None, None]: if not self.wiki_markup: yield self.tag for attr in self.attributes: @@ -110,7 +112,7 @@ class Tag(Node): if not self.wiki_markup and self.closing_tag: yield self.closing_tag - def __strip__(self, **kwargs: Any) -> Optional[str]: + def __strip__(self, **kwargs: Any) -> str | None: if self.contents and is_visible(str(self.tag)): return self.contents.strip_code(**kwargs) return None @@ -118,7 +120,7 @@ class Tag(Node): def __showtree__( self, write: Callable[[str], None], - get: Callable[["Wikicode"], None], + get: Callable[[Wikicode], None], mark: Callable[[], None], ) -> None: write("") @property - def tag(self) -> "Wikicode": + def tag(self) -> Wikicode: """The tag itself, as a :class:`.Wikicode` object.""" return self._tag @@ -149,7 +151,7 @@ class Tag(Node): self._tag = self._closing_tag = parse_anything(value) @property - def contents(self) -> "Wikicode": + def contents(self) -> Wikicode: """The contents of the tag, as a :class:`.Wikicode` object.""" return self._contents @@ -158,7 +160,7 @@ class Tag(Node): self._contents = parse_anything(value) @property - def attributes(self) -> List[Attribute]: + def attributes(self) -> list[Attribute]: """The list of attributes affecting the tag. Each attribute is an instance of :class:`.Attribute`. @@ -166,7 +168,7 @@ class Tag(Node): return self._attrs @property - def wiki_markup(self) -> Optional[str]: + def wiki_markup(self) -> str | None: """The wikified version of a tag to show instead of HTML. If set to a value, this will be displayed instead of the brackets. @@ -176,7 +178,7 @@ class Tag(Node): return self._wiki_markup @wiki_markup.setter - def wiki_markup(self, value: Optional[str]) -> None: + def wiki_markup(self, value: str | None) -> None: self._wiki_markup = str(value) if value else None if not value or not self.closing_wiki_markup: self._closing_wiki_markup = self._wiki_markup @@ -235,7 +237,7 @@ class Tag(Node): self._padding = value @property - def closing_tag(self) -> "Wikicode": + def closing_tag(self) -> Wikicode: """The closing tag, as a :class:`.Wikicode` object. This will usually equal :attr:`tag`, unless there is additional @@ -248,7 +250,7 @@ class Tag(Node): self._closing_tag = parse_anything(value) @property - def wiki_style_separator(self) -> Optional[str]: + def wiki_style_separator(self) -> str | None: """The separator between the padding and content in a wiki markup tag. Essentially the wiki equivalent of the TagCloseOpen. @@ -256,11 +258,11 @@ class Tag(Node): return self._wiki_style_separator @wiki_style_separator.setter - def wiki_style_separator(self, value: Optional[str]) -> None: + def wiki_style_separator(self, value: str | None) -> None: self._wiki_style_separator = str(value) if value else None @property - def closing_wiki_markup(self) -> Optional[str]: + def closing_wiki_markup(self) -> str | None: """The wikified version of the closing tag to show instead of HTML. If set to a value, this will be displayed instead of the close tag @@ -273,7 +275,7 @@ class Tag(Node): return self._closing_wiki_markup @closing_wiki_markup.setter - def closing_wiki_markup(self, value: Optional[str]) -> None: + def closing_wiki_markup(self, value: str | None) -> None: self._closing_wiki_markup = str(value) if value else None def has(self, name: str) -> bool: @@ -304,7 +306,7 @@ class Tag(Node): self, name: Any, value: Any = None, - quotes: Optional[str] = '"', + quotes: str | None = '"', pad_first: str = " ", pad_before_eq: str = "", pad_after_eq: str = "", diff --git a/src/mwparserfromhell/nodes/template.py b/src/mwparserfromhell/nodes/template.py index 46066ef..4a4ea88 100644 --- a/src/mwparserfromhell/nodes/template.py +++ b/src/mwparserfromhell/nodes/template.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -17,27 +17,25 @@ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. + +from __future__ import annotations + import re from collections import defaultdict +from collections.abc import Generator, Mapping from typing import ( TYPE_CHECKING, Any, Callable, - Dict, - Generator, - List, - Mapping, - Optional, TypeVar, - Union, overload, ) +from ..utils import parse_anything from ._base import Node +from .extras import Parameter from .html_entity import HTMLEntity from .text import Text -from .extras import Parameter -from ..utils import parse_anything if TYPE_CHECKING: from ..wikicode import Wikicode @@ -54,10 +52,10 @@ T = TypeVar("T") class Template(Node): """Represents a template in wikicode, like ``{{foo}}``.""" - def __init__(self, name: Any, params: Optional[List[Parameter]] = None): + def __init__(self, name: Any, params: list[Parameter] | None = None): super().__init__() self.name = name - self._params: List[Parameter] = params or [] + self._params: list[Parameter] = params or [] def __str__(self) -> str: if self.params: @@ -65,14 +63,14 @@ class Template(Node): return "{{" + str(self.name) + "|" + params + "}}" return "{{" + str(self.name) + "}}" - def __children__(self) -> Generator["Wikicode", None, None]: + def __children__(self) -> Generator[Wikicode]: yield self.name for param in self.params: if param.showkey: yield param.name yield param.value - def __strip__(self, **kwargs: Any) -> Optional[str]: + def __strip__(self, **kwargs: Any) -> str | None: if kwargs.get("keep_template_params"): parts = [param.value.strip_code(**kwargs) for param in self.params] return " ".join(part for part in parts if part) @@ -81,7 +79,7 @@ class Template(Node): def __showtree__( self, write: Callable[[str], None], - get: Callable[["Wikicode"], None], + get: Callable[[Wikicode], None], mark: Callable[[], None], ) -> None: write("{{") @@ -96,7 +94,7 @@ class Template(Node): write("}}") @staticmethod - def _surface_escape(code: "Wikicode", char: str) -> None: + def _surface_escape(code: Wikicode, char: str) -> None: """Return *code* with *char* escaped as an HTML entity. The main use of this is to escape pipes (``|``) or equal signs (``=``) @@ -109,7 +107,7 @@ class Template(Node): code.replace(node, node.replace(char, replacement), False) @staticmethod - def _select_theory(theories: Dict[str, int]) -> Optional[str]: + def _select_theory(theories: dict[str, int]) -> str | None: """Return the most likely spacing convention given different options. Given a dictionary of convention options as keys and their occurrence @@ -125,7 +123,7 @@ class Template(Node): return None @staticmethod - def _blank_param_value(value: "Wikicode") -> None: + def _blank_param_value(value: Wikicode) -> None: """Remove the content from *value* while keeping its whitespace. Replace *value*\\ 's nodes with two text nodes, the first containing @@ -142,15 +140,15 @@ class Template(Node): def _get_spacing_conventions( self, use_names: bool - ) -> tuple[Optional[str], Optional[str]]: + ) -> tuple[str | None, str | None]: """Try to determine the whitespace conventions for parameters. This will examine the existing parameters and use :meth:`_select_theory` to determine if there are any preferred styles for how much whitespace to put before or after the value. """ - before_theories: defaultdict[str, int] = defaultdict(lambda: 0) - after_theories: defaultdict[str, int] = defaultdict(lambda: 0) + before_theories: defaultdict[str, int] = defaultdict(int) + after_theories: defaultdict[str, int] = defaultdict(int) for param in self.params: if not param.showkey: continue @@ -205,7 +203,7 @@ class Template(Node): return False @property - def name(self) -> "Wikicode": + def name(self) -> Wikicode: """The name of the template, as a :class:`.Wikicode` object.""" return self._name @@ -214,11 +212,11 @@ class Template(Node): self._name = parse_anything(value) @property - def params(self) -> List[Parameter]: + def params(self) -> list[Parameter]: """The list of parameters contained within the template.""" return self._params - def has(self, name: Union[str, Any], ignore_empty: bool = False) -> bool: + def has(self, name: str | Any, ignore_empty: bool = False) -> bool: """Return ``True`` if any parameter in the template is named *name*. With *ignore_empty*, ``False`` will be returned even if the template @@ -234,17 +232,17 @@ class Template(Node): return True return False - def has_param(self, name: Union[str, Any], ignore_empty: bool = False) -> bool: + def has_param(self, name: str | Any, ignore_empty: bool = False) -> bool: """Alias for :meth:`has`.""" return self.has(name, ignore_empty) @overload - def get(self, name: Union[str, Any]) -> Parameter: ... + def get(self, name: str | Any) -> Parameter: ... @overload - def get(self, name: Union[str, Any], default: T) -> Union[Parameter, T]: ... + def get(self, name: str | Any, default: T) -> Parameter | T: ... - def get(self, name: Union[str, Any], default: T = _UNSET) -> Union[Parameter, T]: + def get(self, name: str | Any, default: T = _UNSET) -> Parameter | T: """Get the parameter whose name is *name*. The returned object is a :class:`.Parameter` instance. Raises @@ -261,16 +259,16 @@ class Template(Node): raise ValueError(name) return default - def __getitem__(self, name: Union[str, Any]) -> Parameter: + def __getitem__(self, name: str | Any) -> Parameter: return self.get(name) def add( self, name: Any, value: Any, - showkey: Optional[bool] = None, - before: Optional[Union[Parameter, str]] = None, - after: Optional[Union[Parameter, str]] = None, + showkey: bool | None = None, + before: Parameter | str | None = None, + after: Parameter | str | None = None, preserve_spacing: bool = True, ) -> Parameter: """Add a parameter to the template with a given *name* and *value*. @@ -377,7 +375,7 @@ class Template(Node): def __setitem__(self, name: Any, value: Any) -> Parameter: return self.add(name, value) - def remove(self, param: Union[Parameter, str], keep_field: bool = False) -> None: + def remove(self, param: Parameter | str, keep_field: bool = False) -> None: """Remove a parameter from the template, identified by *param*. If *param* is a :class:`.Parameter` object, it will be matched exactly, @@ -424,5 +422,5 @@ class Template(Node): for i in reversed(to_remove): self.params.pop(i) - def __delitem__(self, param: Union[Parameter, str]) -> None: + def __delitem__(self, param: Parameter | str) -> None: return self.remove(param) diff --git a/src/mwparserfromhell/nodes/text.py b/src/mwparserfromhell/nodes/text.py index 6847645..0aad960 100644 --- a/src/mwparserfromhell/nodes/text.py +++ b/src/mwparserfromhell/nodes/text.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -18,6 +18,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +from __future__ import annotations from typing import TYPE_CHECKING, Any, Callable @@ -45,7 +46,7 @@ class Text(Node): def __showtree__( self, write: Callable[[str], None], - get: Callable[["Wikicode"], None], + get: Callable[[Wikicode], None], mark: Callable[[], None], ) -> None: write(str(self).encode("unicode_escape").decode("utf8")) diff --git a/src/mwparserfromhell/nodes/wikilink.py b/src/mwparserfromhell/nodes/wikilink.py index 3378778..f367985 100644 --- a/src/mwparserfromhell/nodes/wikilink.py +++ b/src/mwparserfromhell/nodes/wikilink.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -18,11 +18,13 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +from __future__ import annotations -from typing import TYPE_CHECKING, Any, Optional, Generator, Callable +from collections.abc import Generator +from typing import TYPE_CHECKING, Any, Callable -from ._base import Node from ..utils import parse_anything +from ._base import Node if TYPE_CHECKING: from ..wikicode import Wikicode @@ -43,12 +45,12 @@ class Wikilink(Node): return "[[" + str(self.title) + "|" + str(self.text) + "]]" return "[[" + str(self.title) + "]]" - def __children__(self) -> Generator["Wikicode", None, None]: + def __children__(self) -> Generator[Wikicode, None, None]: yield self.title if self.text is not None: yield self.text - def __strip__(self, **kwargs: Any) -> Optional[str]: + def __strip__(self, **kwargs: Any) -> str | None: if self.text is not None: return self.text.strip_code(**kwargs) return self.title.strip_code(**kwargs) @@ -56,7 +58,7 @@ class Wikilink(Node): def __showtree__( self, write: Callable[[str], None], - get: Callable[["Wikicode"], None], + get: Callable[[Wikicode], None], mark: Callable[[], None], ) -> None: write("[[") @@ -68,7 +70,7 @@ class Wikilink(Node): write("]]") @property - def title(self) -> "Wikicode": + def title(self) -> Wikicode: """The title of the linked page, as a :class:`.Wikicode` object.""" return self._title @@ -77,7 +79,7 @@ class Wikilink(Node): self._title = parse_anything(value) @property - def text(self) -> Optional["Wikicode"]: + def text(self) -> Wikicode | None: """The text to display (if any), as a :class:`.Wikicode` object.""" return self._text diff --git a/src/mwparserfromhell/parser/__init__.py b/src/mwparserfromhell/parser/__init__.py index d1991bb..0a2b4d1 100644 --- a/src/mwparserfromhell/parser/__init__.py +++ b/src/mwparserfromhell/parser/__init__.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -24,6 +24,8 @@ modules: the :mod:`.tokenizer` and the :mod:`.builder`. This module joins them together into one interface. """ +from __future__ import annotations + from .builder import Builder from .errors import ParserError diff --git a/src/mwparserfromhell/parser/builder.py b/src/mwparserfromhell/parser/builder.py index 9e4fa03..e660118 100644 --- a/src/mwparserfromhell/parser/builder.py +++ b/src/mwparserfromhell/parser/builder.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -18,9 +18,8 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +from __future__ import annotations -from . import tokens -from .errors import ParserError from ..nodes import ( Argument, Comment, @@ -35,6 +34,8 @@ from ..nodes import ( from ..nodes.extras import Attribute, Parameter from ..smart_list import SmartList from ..wikicode import Wikicode +from . import tokens +from .errors import ParserError __all__ = ["Builder"] diff --git a/src/mwparserfromhell/parser/contexts.py b/src/mwparserfromhell/parser/contexts.py index e0697f9..4896085 100644 --- a/src/mwparserfromhell/parser/contexts.py +++ b/src/mwparserfromhell/parser/contexts.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2019 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -114,6 +114,8 @@ Aggregate contexts: """ +from __future__ import annotations + # Local contexts: TEMPLATE_NAME = 1 << 0 diff --git a/src/mwparserfromhell/parser/ctokenizer/common.h b/src/mwparserfromhell/parser/ctokenizer/common.h index b3e9cec..dbd13b6 100644 --- a/src/mwparserfromhell/parser/ctokenizer/common.h +++ b/src/mwparserfromhell/parser/ctokenizer/common.h @@ -1,5 +1,5 @@ /* -Copyright (C) 2012-2017 Ben Kurtovic +Copyright (C) 2012-2025 Ben Kurtovic Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/src/mwparserfromhell/parser/ctokenizer/contexts.h b/src/mwparserfromhell/parser/ctokenizer/contexts.h index e20e67d..d6f2465 100644 --- a/src/mwparserfromhell/parser/ctokenizer/contexts.h +++ b/src/mwparserfromhell/parser/ctokenizer/contexts.h @@ -1,5 +1,5 @@ /* -Copyright (C) 2012-2017 Ben Kurtovic +Copyright (C) 2012-2025 Ben Kurtovic Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/src/mwparserfromhell/parser/ctokenizer/definitions.c b/src/mwparserfromhell/parser/ctokenizer/definitions.c index 06612e4..d5f7393 100644 --- a/src/mwparserfromhell/parser/ctokenizer/definitions.c +++ b/src/mwparserfromhell/parser/ctokenizer/definitions.c @@ -1,5 +1,5 @@ /* -Copyright (C) 2012-2020 Ben Kurtovic +Copyright (C) 2012-2025 Ben Kurtovic Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/src/mwparserfromhell/parser/ctokenizer/definitions.h b/src/mwparserfromhell/parser/ctokenizer/definitions.h index bb4c657..481f208 100644 --- a/src/mwparserfromhell/parser/ctokenizer/definitions.h +++ b/src/mwparserfromhell/parser/ctokenizer/definitions.h @@ -1,5 +1,5 @@ /* -Copyright (C) 2012-2016 Ben Kurtovic +Copyright (C) 2012-2025 Ben Kurtovic Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/src/mwparserfromhell/parser/ctokenizer/tag_data.c b/src/mwparserfromhell/parser/ctokenizer/tag_data.c index f4e1464..241381c 100644 --- a/src/mwparserfromhell/parser/ctokenizer/tag_data.c +++ b/src/mwparserfromhell/parser/ctokenizer/tag_data.c @@ -1,5 +1,5 @@ /* -Copyright (C) 2012-2016 Ben Kurtovic +Copyright (C) 2012-2025 Ben Kurtovic Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/src/mwparserfromhell/parser/ctokenizer/tag_data.h b/src/mwparserfromhell/parser/ctokenizer/tag_data.h index 70db867..de0491b 100644 --- a/src/mwparserfromhell/parser/ctokenizer/tag_data.h +++ b/src/mwparserfromhell/parser/ctokenizer/tag_data.h @@ -1,5 +1,5 @@ /* -Copyright (C) 2012-2016 Ben Kurtovic +Copyright (C) 2012-2025 Ben Kurtovic Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/src/mwparserfromhell/parser/ctokenizer/textbuffer.c b/src/mwparserfromhell/parser/ctokenizer/textbuffer.c index 4591f91..5971a68 100644 --- a/src/mwparserfromhell/parser/ctokenizer/textbuffer.c +++ b/src/mwparserfromhell/parser/ctokenizer/textbuffer.c @@ -1,5 +1,5 @@ /* -Copyright (C) 2012-2016 Ben Kurtovic +Copyright (C) 2012-2025 Ben Kurtovic Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/src/mwparserfromhell/parser/ctokenizer/textbuffer.h b/src/mwparserfromhell/parser/ctokenizer/textbuffer.h index e7db0c1..946eaf5 100644 --- a/src/mwparserfromhell/parser/ctokenizer/textbuffer.h +++ b/src/mwparserfromhell/parser/ctokenizer/textbuffer.h @@ -1,5 +1,5 @@ /* -Copyright (C) 2012-2016 Ben Kurtovic +Copyright (C) 2012-2025 Ben Kurtovic Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/src/mwparserfromhell/parser/ctokenizer/tok_parse.c b/src/mwparserfromhell/parser/ctokenizer/tok_parse.c index d3e83ef..f42add1 100644 --- a/src/mwparserfromhell/parser/ctokenizer/tok_parse.c +++ b/src/mwparserfromhell/parser/ctokenizer/tok_parse.c @@ -1,5 +1,5 @@ /* -Copyright (C) 2012-2021 Ben Kurtovic +Copyright (C) 2012-2025 Ben Kurtovic Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/src/mwparserfromhell/parser/ctokenizer/tok_parse.h b/src/mwparserfromhell/parser/ctokenizer/tok_parse.h index 9a8f948..d72b2b2 100644 --- a/src/mwparserfromhell/parser/ctokenizer/tok_parse.h +++ b/src/mwparserfromhell/parser/ctokenizer/tok_parse.h @@ -1,5 +1,5 @@ /* -Copyright (C) 2012-2016 Ben Kurtovic +Copyright (C) 2012-2025 Ben Kurtovic Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/src/mwparserfromhell/parser/ctokenizer/tok_support.c b/src/mwparserfromhell/parser/ctokenizer/tok_support.c index bd1e440..4c495ce 100644 --- a/src/mwparserfromhell/parser/ctokenizer/tok_support.c +++ b/src/mwparserfromhell/parser/ctokenizer/tok_support.c @@ -1,5 +1,5 @@ /* -Copyright (C) 2012-2018 Ben Kurtovic +Copyright (C) 2012-2025 Ben Kurtovic Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/src/mwparserfromhell/parser/ctokenizer/tok_support.h b/src/mwparserfromhell/parser/ctokenizer/tok_support.h index e8a9c63..5dee522 100644 --- a/src/mwparserfromhell/parser/ctokenizer/tok_support.h +++ b/src/mwparserfromhell/parser/ctokenizer/tok_support.h @@ -1,5 +1,5 @@ /* -Copyright (C) 2012-2018 Ben Kurtovic +Copyright (C) 2012-2025 Ben Kurtovic Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/src/mwparserfromhell/parser/ctokenizer/tokenizer.c b/src/mwparserfromhell/parser/ctokenizer/tokenizer.c index 5b353e9..b4feb87 100644 --- a/src/mwparserfromhell/parser/ctokenizer/tokenizer.c +++ b/src/mwparserfromhell/parser/ctokenizer/tokenizer.c @@ -1,5 +1,5 @@ /* -Copyright (C) 2012-2017 Ben Kurtovic +Copyright (C) 2012-2025 Ben Kurtovic Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/src/mwparserfromhell/parser/ctokenizer/tokenizer.h b/src/mwparserfromhell/parser/ctokenizer/tokenizer.h index 8c3d41e..6c42071 100644 --- a/src/mwparserfromhell/parser/ctokenizer/tokenizer.h +++ b/src/mwparserfromhell/parser/ctokenizer/tokenizer.h @@ -1,5 +1,5 @@ /* -Copyright (C) 2012-2016 Ben Kurtovic +Copyright (C) 2012-2025 Ben Kurtovic Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/src/mwparserfromhell/parser/ctokenizer/tokens.c b/src/mwparserfromhell/parser/ctokenizer/tokens.c index 69edec3..5fa6875 100644 --- a/src/mwparserfromhell/parser/ctokenizer/tokens.c +++ b/src/mwparserfromhell/parser/ctokenizer/tokens.c @@ -1,5 +1,5 @@ /* -Copyright (C) 2012-2016 Ben Kurtovic +Copyright (C) 2012-2025 Ben Kurtovic Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/src/mwparserfromhell/parser/ctokenizer/tokens.h b/src/mwparserfromhell/parser/ctokenizer/tokens.h index 153c5ad..1e77306 100644 --- a/src/mwparserfromhell/parser/ctokenizer/tokens.h +++ b/src/mwparserfromhell/parser/ctokenizer/tokens.h @@ -1,5 +1,5 @@ /* -Copyright (C) 2012-2016 Ben Kurtovic +Copyright (C) 2012-2025 Ben Kurtovic Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/src/mwparserfromhell/parser/errors.py b/src/mwparserfromhell/parser/errors.py index 190b653..550db88 100644 --- a/src/mwparserfromhell/parser/errors.py +++ b/src/mwparserfromhell/parser/errors.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -18,6 +18,8 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +from __future__ import annotations + __all__ = ["ParserError"] @@ -31,5 +33,5 @@ class ParserError(Exception): """ def __init__(self, extra): - msg = "This is a bug and should be reported. Info: {}.".format(extra) + msg = f"This is a bug and should be reported. Info: {extra}." super().__init__(msg) diff --git a/src/mwparserfromhell/parser/tokenizer.py b/src/mwparserfromhell/parser/tokenizer.py index 4a0fc24..a1da548 100644 --- a/src/mwparserfromhell/parser/tokenizer.py +++ b/src/mwparserfromhell/parser/tokenizer.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2021 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -18,19 +18,21 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +from __future__ import annotations + import html.entities as htmlentities -from math import log import re +from math import log -from . import contexts, tokens -from .errors import ParserError from ..definitions import ( get_html_tag, is_parsable, + is_scheme, is_single, is_single_only, - is_scheme, ) +from . import contexts, tokens +from .errors import ParserError __all__ = ["Tokenizer"] diff --git a/src/mwparserfromhell/parser/tokens.py b/src/mwparserfromhell/parser/tokens.py index 44ffe40..d0af9fb 100644 --- a/src/mwparserfromhell/parser/tokens.py +++ b/src/mwparserfromhell/parser/tokens.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,8 @@ a syntactically valid form by the :class:`.Tokenizer`, and then converted into the :class`.Wikicode` tree by the :class:`.Builder`. """ +from __future__ import annotations + __all__ = ["Token"] diff --git a/src/mwparserfromhell/smart_list/__init__.py b/src/mwparserfromhell/smart_list/__init__.py index da7003d..599adc2 100644 --- a/src/mwparserfromhell/smart_list/__init__.py +++ b/src/mwparserfromhell/smart_list/__init__.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # Copyright (C) 2019-2020 Yuri Astrakhan # # Permission is hereby granted, free of charge, to any person obtaining a copy @@ -25,6 +25,8 @@ This module contains the :class:`.SmartList` type, as well as its reflect changes made to the main list, and vice-versa. """ +from __future__ import annotations + __all__ = ["SmartList"] from .smart_list import SmartList diff --git a/src/mwparserfromhell/smart_list/list_proxy.py b/src/mwparserfromhell/smart_list/list_proxy.py index f726754..c68b167 100644 --- a/src/mwparserfromhell/smart_list/list_proxy.py +++ b/src/mwparserfromhell/smart_list/list_proxy.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2023 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # Copyright (C) 2019-2020 Yuri Astrakhan # # Permission is hereby granted, free of charge, to any person obtaining a copy @@ -19,6 +19,8 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +from __future__ import annotations + import weakref from .utils import _SliceNormalizerMixIn, inheritdoc diff --git a/src/mwparserfromhell/smart_list/smart_list.py b/src/mwparserfromhell/smart_list/smart_list.py index dbd09ca..4196112 100644 --- a/src/mwparserfromhell/smart_list/smart_list.py +++ b/src/mwparserfromhell/smart_list/smart_list.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2023 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # Copyright (C) 2019-2020 Yuri Astrakhan # # Permission is hereby granted, free of charge, to any person obtaining a copy @@ -19,6 +19,8 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +from __future__ import annotations + from weakref import ref from .list_proxy import ListProxy diff --git a/src/mwparserfromhell/smart_list/utils.py b/src/mwparserfromhell/smart_list/utils.py index ec2d388..8a22906 100644 --- a/src/mwparserfromhell/smart_list/utils.py +++ b/src/mwparserfromhell/smart_list/utils.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2023 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # Copyright (C) 2019-2020 Yuri Astrakhan # # Permission is hereby granted, free of charge, to any person obtaining a copy @@ -19,6 +19,8 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +from __future__ import annotations + from sys import maxsize __all__ = [] diff --git a/src/mwparserfromhell/string_mixin.py b/src/mwparserfromhell/string_mixin.py index a342de4..d3d03d1 100644 --- a/src/mwparserfromhell/string_mixin.py +++ b/src/mwparserfromhell/string_mixin.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -23,6 +23,8 @@ This module contains the :class:`.StringMixIn` type, which implements the interface for the ``str`` type in a dynamic manner. """ +from __future__ import annotations + from sys import getdefaultencoding __all__ = ["StringMixIn"] @@ -95,7 +97,7 @@ class StringMixIn: def __getattr__(self, attr): if not hasattr(str, attr): raise AttributeError( - "{!r} object has no attribute {!r}".format(type(self).__name__, attr) + f"{type(self).__name__!r} object has no attribute {attr!r}" ) return getattr(self.__str__(), attr) diff --git a/src/mwparserfromhell/utils.py b/src/mwparserfromhell/utils.py index d049d71..7752e65 100644 --- a/src/mwparserfromhell/utils.py +++ b/src/mwparserfromhell/utils.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2023 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal diff --git a/src/mwparserfromhell/wikicode.py b/src/mwparserfromhell/wikicode.py index e84cb21..9bd5c3f 100644 --- a/src/mwparserfromhell/wikicode.py +++ b/src/mwparserfromhell/wikicode.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -18,9 +18,12 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +from __future__ import annotations + import re +from collections.abc import Generator, Iterable from itertools import chain -from typing import Any, Callable, Generator, Iterable, Optional, Union, cast, overload +from typing import Any, Callable, cast, overload from .nodes import ( Argument, @@ -67,9 +70,9 @@ class Wikicode(StringMixIn): def _get_children( node: Node, contexts: bool = False, - restrict: Optional[type] = None, - parent: Optional["Wikicode"] = None, - ) -> Generator[Union[tuple[Optional["Wikicode"], Node], Node], None, None]: + restrict: type | None = None, + parent: Wikicode | None = None, + ) -> Generator[tuple[Wikicode | None, Node] | Node]: """Iterate over all child :class:`.Node`\\ s of a given *node*.""" yield (parent, node) if contexts else node if restrict and isinstance(node, restrict): @@ -80,7 +83,7 @@ class Wikicode(StringMixIn): yield from sub @staticmethod - def _slice_replace(code: "Wikicode", index: slice, old: str, new: str) -> None: + def _slice_replace(code: Wikicode, index: slice, old: str, new: str) -> None: """Replace the string *old* with *new* across *index* in *code*.""" nodes = [str(node) for node in code.get(index)] substring = "".join(nodes).replace(old, new) @@ -88,11 +91,11 @@ class Wikicode(StringMixIn): @staticmethod def _build_matcher( - matches: Union[ - Callable[[Node], Union[bool, re.Match[str], None]], re.Pattern, str, None - ], + matches: ( + Callable[[Node], bool | re.Match[str] | None] | re.Pattern | str | None + ), flags: int, - ) -> Callable[[Node], Union[bool, re.Match[str], None]]: + ) -> Callable[[Node], bool | re.Match[str] | None]: """Helper for :meth:`_indexed_ifilter` and others. If *matches* is a function, return it. If it's a regex, return a @@ -108,10 +111,10 @@ class Wikicode(StringMixIn): def _indexed_ifilter( self, recursive: bool = True, - matches: Union[Callable[[Node], bool], re.Pattern, str, None] = None, + matches: Callable[[Node], bool] | re.Pattern | str | None = None, flags: int = FLAGS, - forcetype: Optional[type] = None, - ) -> Generator[tuple[int, Node], None, None]: + forcetype: type | None = None, + ) -> Generator[tuple[int, Node]]: """Iterate over nodes and their corresponding indices in the node list. The arguments are interpreted as for :meth:`ifilter`. For each tuple @@ -124,7 +127,7 @@ class Wikicode(StringMixIn): if recursive: restrict = forcetype if recursive == self.RECURSE_OTHERS else None - def getter(i: int, node: Node) -> Generator[tuple[int, Node], None, None]: + def getter(i: int, node: Node) -> Generator[tuple[int, Node]]: for ch in self._get_children(node, restrict=restrict): yield (i, cast(Node, ch)) @@ -135,7 +138,7 @@ class Wikicode(StringMixIn): if (not forcetype or isinstance(node, forcetype)) and match(node): yield (i, node) - def _is_child_wikicode(self, obj: "Wikicode", recursive: bool = True) -> bool: + def _is_child_wikicode(self, obj: Wikicode, recursive: bool = True) -> bool: """Return whether the given :class:`.Wikicode` is a descendant.""" def deref(nodes): @@ -157,8 +160,8 @@ class Wikicode(StringMixIn): return False def _do_strong_search( - self, obj: Union[Node, "Wikicode"], recursive: bool = True - ) -> tuple["Wikicode", slice]: + self, obj: Node | Wikicode, recursive: bool = True + ) -> tuple[Wikicode, slice]: """Search for the specific element *obj* within the node list. *obj* can be either a :class:`.Node` or a :class:`.Wikicode` object. If @@ -194,7 +197,7 @@ class Wikicode(StringMixIn): def _do_weak_search( self, obj: Any, recursive: bool - ) -> list[tuple[bool, "Wikicode", slice]]: + ) -> list[tuple[bool, Wikicode, slice]]: """Search for an element that looks like *obj* within the node list. This follows the same rules as :meth:`_do_strong_search` with some @@ -215,7 +218,7 @@ class Wikicode(StringMixIn): if not obj or obj not in self: raise ValueError(obj) results = [] - contexts: list["Wikicode"] = [self] + contexts: list[Wikicode] = [self] while contexts: context = contexts.pop() i = len(context.nodes) - 1 @@ -239,7 +242,7 @@ class Wikicode(StringMixIn): return results def _get_tree( - self, code: "Wikicode", lines: list[str], marker: Any, indent: int + self, code: Wikicode, lines: list[str], marker: Any, indent: int ) -> list[str]: """Build a tree to illustrate the way the Wikicode object was parsed. @@ -314,7 +317,7 @@ class Wikicode(StringMixIn): return self._nodes @nodes.setter - def nodes(self, value: Union[list[Node], Any]) -> None: + def nodes(self, value: list[Node] | Any) -> None: if not isinstance(value, list): value = parse_anything(value).nodes self._nodes = value @@ -347,7 +350,7 @@ class Wikicode(StringMixIn): else: self.nodes.pop(index) - def contains(self, obj: Union[Node, "Wikicode", str]) -> bool: + def contains(self, obj: Node | Wikicode | str) -> bool: """Return whether this Wikicode object contains *obj*. If *obj* is a :class:`.Node` or :class:`.Wikicode` object, then we @@ -362,7 +365,7 @@ class Wikicode(StringMixIn): return False return True - def index(self, obj: Union[Node, "Wikicode", str], recursive: bool = False) -> int: + def index(self, obj: Node | Wikicode | str, recursive: bool = False) -> int: """Return the index of *obj* in the list of nodes. Raises :exc:`ValueError` if *obj* is not found. If *recursive* is @@ -381,7 +384,7 @@ class Wikicode(StringMixIn): return i raise ValueError(obj) - def get_ancestors(self, obj: Union[Node, "Wikicode"]) -> list[Node]: + def get_ancestors(self, obj: Node | Wikicode) -> list[Node]: """Return a list of all ancestor nodes of the :class:`.Node` *obj*. The list is ordered from the most shallow ancestor (greatest great- @@ -398,7 +401,7 @@ class Wikicode(StringMixIn): object. Will raise :exc:`ValueError` if it wasn't found. """ - def _get_ancestors(code: "Wikicode", needle: Node) -> Union[list[Node], None]: + def _get_ancestors(code: Wikicode, needle: Node) -> list[Node] | None: for node in code.nodes: if node is needle: return [] @@ -418,7 +421,7 @@ class Wikicode(StringMixIn): raise ValueError(obj) return ancestors - def get_parent(self, obj: Union[Node, "Wikicode"]) -> Union[Node, None]: + def get_parent(self, obj: Node | Wikicode) -> Node | None: """Return the direct parent node of the :class:`.Node` *obj*. This function is equivalent to calling :meth:`.get_ancestors` and @@ -440,7 +443,7 @@ class Wikicode(StringMixIn): self.nodes.insert(index, node) def insert_before( - self, obj: Union[Node, "Wikicode", str], value: Any, recursive: bool = True + self, obj: Node | Wikicode | str, value: Any, recursive: bool = True ) -> None: """Insert *value* immediately before *obj*. @@ -465,7 +468,7 @@ class Wikicode(StringMixIn): self._slice_replace(context, index, obj, str(value) + obj) def insert_after( - self, obj: Union[Node, "Wikicode", str], value: Any, recursive: bool = True + self, obj: Node | Wikicode | str, value: Any, recursive: bool = True ) -> None: """Insert *value* immediately after *obj*. @@ -490,7 +493,7 @@ class Wikicode(StringMixIn): self._slice_replace(context, index, obj, obj + str(value)) def replace( - self, obj: Union[Node, "Wikicode", str], value: Any, recursive: bool = True + self, obj: Node | Wikicode | str, value: Any, recursive: bool = True ) -> None: """Replace *obj* with *value*. @@ -526,7 +529,7 @@ class Wikicode(StringMixIn): for node in nodes: self.nodes.append(node) - def remove(self, obj: Union[Node, "Wikicode", str], recursive: bool = True) -> None: + def remove(self, obj: Node | Wikicode | str, recursive: bool = True) -> None: """Remove *obj* from the list of nodes. *obj* can be either a string, a :class:`.Node`, or another @@ -552,9 +555,7 @@ class Wikicode(StringMixIn): def matches( self, - other: Union[ - Node, "Wikicode", str, bytes, Iterable[Union[Node, "Wikicode", str, bytes]] - ], + other: Node | Wikicode | str | bytes | Iterable[Node | Wikicode | str | bytes], ) -> bool: """Do a loose equivalency test suitable for comparing page names. @@ -583,10 +584,10 @@ class Wikicode(StringMixIn): def ifilter( self, recursive: bool = True, - matches: Union[Callable[[Node], bool], re.Pattern, str, None] = None, + matches: Callable[[Node], bool] | re.Pattern | str | None = None, flags: int = FLAGS, - forcetype: Optional[type] = None, - ) -> Generator[Node, None, None]: + forcetype: type | None = None, + ) -> Generator[Node]: """Iterate over nodes in our list matching certain conditions. If *forcetype* is given, only nodes that are instances of this type (or @@ -622,13 +623,13 @@ class Wikicode(StringMixIn): def get_sections( self, - levels: Optional[Iterable[int]] = None, - matches: Union[Callable[[Node], bool], re.Pattern, str, None] = None, + levels: Iterable[int] | None = None, + matches: Callable[[Node], bool] | re.Pattern | str | None = None, flags: int = FLAGS, flat: bool = False, - include_lead: Optional[bool] = None, + include_lead: bool | None = None, include_headings: bool = True, - ) -> list["Wikicode"]: + ) -> list[Wikicode]: """Return a list of sections within the page. Sections are returned as :class:`.Wikicode` objects with a shared node diff --git a/tests/conftest.py b/tests/conftest.py index dc8655d..a0938fd 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2021 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -18,6 +18,8 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +from __future__ import annotations + from mwparserfromhell.nodes import ( Argument, Comment, diff --git a/tests/test_argument.py b/tests/test_argument.py index 2617af3..17a2884 100644 --- a/tests/test_argument.py +++ b/tests/test_argument.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -22,9 +22,12 @@ Test cases for the Argument node. """ +from __future__ import annotations + import pytest from mwparserfromhell.nodes import Argument, Text + from .conftest import assert_wikicode_equal, wrap, wraptext diff --git a/tests/test_attribute.py b/tests/test_attribute.py index 0d67f2a..f3a641d 100644 --- a/tests/test_attribute.py +++ b/tests/test_attribute.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -22,10 +22,13 @@ Test cases for the Attribute node extra. """ +from __future__ import annotations + import pytest from mwparserfromhell.nodes import Template from mwparserfromhell.nodes.extras import Attribute + from .conftest import assert_wikicode_equal, wrap, wraptext diff --git a/tests/test_builder.py b/tests/test_builder.py index 2a4eb4a..13b6bbd 100644 --- a/tests/test_builder.py +++ b/tests/test_builder.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2019 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -22,6 +22,8 @@ Tests for the builder, which turns tokens into Wikicode objects. """ +from __future__ import annotations + import pytest from mwparserfromhell.nodes import ( @@ -36,8 +38,9 @@ from mwparserfromhell.nodes import ( Wikilink, ) from mwparserfromhell.nodes.extras import Attribute, Parameter -from mwparserfromhell.parser import tokens, ParserError +from mwparserfromhell.parser import ParserError, tokens from mwparserfromhell.parser.builder import Builder + from .conftest import assert_wikicode_equal, wrap, wraptext diff --git a/tests/test_comment.py b/tests/test_comment.py index 3d3c657..9055036 100644 --- a/tests/test_comment.py +++ b/tests/test_comment.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -22,6 +22,8 @@ Test cases for the Comment node. """ +from __future__ import annotations + import pytest from mwparserfromhell.nodes import Comment diff --git a/tests/test_docs.py b/tests/test_docs.py index 8ac8f6f..582d6c0 100644 --- a/tests/test_docs.py +++ b/tests/test_docs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -22,9 +22,11 @@ Integration test cases for mwparserfromhell's documentation. """ +from __future__ import annotations + import json -from io import StringIO import os +from io import StringIO from urllib.parse import urlencode from urllib.request import urlopen diff --git a/tests/test_external_link.py b/tests/test_external_link.py index 57531de..ef0d4fd 100644 --- a/tests/test_external_link.py +++ b/tests/test_external_link.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -22,9 +22,12 @@ Test cases for the ExternalLink node. """ +from __future__ import annotations + import pytest from mwparserfromhell.nodes import ExternalLink, Text + from .conftest import assert_wikicode_equal, wrap, wraptext diff --git a/tests/test_heading.py b/tests/test_heading.py index 603b6b0..5e9a5e2 100644 --- a/tests/test_heading.py +++ b/tests/test_heading.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -22,9 +22,12 @@ Test cases for the Heading node. """ +from __future__ import annotations + import pytest from mwparserfromhell.nodes import Heading, Text + from .conftest import assert_wikicode_equal, wrap, wraptext diff --git a/tests/test_html_entity.py b/tests/test_html_entity.py index cef999f..d96ae56 100644 --- a/tests/test_html_entity.py +++ b/tests/test_html_entity.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -22,6 +22,8 @@ Test cases for the HTMLEntity node. """ +from __future__ import annotations + import pytest from mwparserfromhell.nodes import HTMLEntity diff --git a/tests/test_parameter.py b/tests/test_parameter.py index 68d8519..7d5127d 100644 --- a/tests/test_parameter.py +++ b/tests/test_parameter.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -22,9 +22,12 @@ Test cases for the Parameter node extra. """ +from __future__ import annotations + import pytest from mwparserfromhell.nodes.extras import Parameter + from .conftest import assert_wikicode_equal, wraptext diff --git a/tests/test_parser.py b/tests/test_parser.py index 8ee7b53..8ec4a40 100644 --- a/tests/test_parser.py +++ b/tests/test_parser.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2016 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -22,11 +22,14 @@ Tests for the Parser class itself, which tokenizes and builds nodes. """ +from __future__ import annotations + import pytest from mwparserfromhell import parser from mwparserfromhell.nodes import Tag, Template, Text, Wikilink from mwparserfromhell.nodes.extras import Parameter + from .conftest import assert_wikicode_equal, wrap, wraptext diff --git a/tests/test_smart_list.py b/tests/test_smart_list.py index 18c0d10..0f2fd9a 100644 --- a/tests/test_smart_list.py +++ b/tests/test_smart_list.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2023 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -22,6 +22,8 @@ Test cases for the SmartList class and its child, ListProxy. """ +from __future__ import annotations + import pickle import pytest diff --git a/tests/test_string_mixin.py b/tests/test_string_mixin.py index 640c3ef..12caeea 100644 --- a/tests/test_string_mixin.py +++ b/tests/test_string_mixin.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -22,6 +22,8 @@ Test cases for the StringMixIn class. """ +from __future__ import annotations + import sys from types import GeneratorType diff --git a/tests/test_tag.py b/tests/test_tag.py index 476aa49..a149575 100644 --- a/tests/test_tag.py +++ b/tests/test_tag.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -22,10 +22,13 @@ Test cases for the Tag node. """ +from __future__ import annotations + import pytest from mwparserfromhell.nodes import Tag, Template, Text from mwparserfromhell.nodes.extras import Attribute + from .conftest import assert_wikicode_equal, wrap, wraptext diff --git a/tests/test_template.py b/tests/test_template.py index a7db195..84fd201 100644 --- a/tests/test_template.py +++ b/tests/test_template.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -22,13 +22,16 @@ Test cases for the Template node. """ +from __future__ import annotations + from difflib import unified_diff import pytest +from mwparserfromhell import parse from mwparserfromhell.nodes import HTMLEntity, Template, Text from mwparserfromhell.nodes.extras import Parameter -from mwparserfromhell import parse + from .conftest import assert_wikicode_equal, wrap, wraptext diff --git a/tests/test_text.py b/tests/test_text.py index 908a7b3..011d779 100644 --- a/tests/test_text.py +++ b/tests/test_text.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -22,6 +22,8 @@ Test cases for the Text node. """ +from __future__ import annotations + import pytest from mwparserfromhell.nodes import Text diff --git a/tests/test_tokenizer.py b/tests/test_tokenizer.py index f7cb9b0..cfa9af6 100644 --- a/tests/test_tokenizer.py +++ b/tests/test_tokenizer.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2016 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -18,9 +18,11 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +from __future__ import annotations + import codecs -from os import listdir, path import warnings +from os import listdir, path import pytest diff --git a/tests/test_tokens.py b/tests/test_tokens.py index f4b2b30..d425205 100644 --- a/tests/test_tokens.py +++ b/tests/test_tokens.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -22,6 +22,8 @@ Test cases for the Token class and its subclasses. """ +from __future__ import annotations + import pytest from mwparserfromhell.parser import tokens diff --git a/tests/test_utils.py b/tests/test_utils.py index 49964f6..49d9b19 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2016 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -22,10 +22,13 @@ Tests for the utils module, which provides parse_anything(). """ +from __future__ import annotations + import pytest from mwparserfromhell.nodes import Template, Text from mwparserfromhell.utils import parse_anything + from .conftest import assert_wikicode_equal, wrap, wraptext diff --git a/tests/test_wikicode.py b/tests/test_wikicode.py index da23a79..515a7b1 100644 --- a/tests/test_wikicode.py +++ b/tests/test_wikicode.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2023 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -22,17 +22,20 @@ Tests for the Wikicode class, which manages a list of nodes. """ -from functools import partial -import re +from __future__ import annotations + import pickle +import re +from functools import partial from types import GeneratorType import pytest +from mwparserfromhell import parse from mwparserfromhell.nodes import Argument, Heading, Template, Text from mwparserfromhell.smart_list import SmartList from mwparserfromhell.wikicode import Wikicode -from mwparserfromhell import parse + from .conftest import wrap, wraptext diff --git a/tests/test_wikilink.py b/tests/test_wikilink.py index 72a8490..b4eec28 100644 --- a/tests/test_wikilink.py +++ b/tests/test_wikilink.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2020 Ben Kurtovic +# Copyright (C) 2012-2025 Ben Kurtovic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -22,9 +22,12 @@ Test cases for the Wikilink node. """ +from __future__ import annotations + import pytest from mwparserfromhell.nodes import Text, Wikilink + from .conftest import assert_wikicode_equal, wrap, wraptext