diff --git a/src/mwparserfromhell/nodes/tag.py b/src/mwparserfromhell/nodes/tag.py
index 027b09c..bf4ad40 100644
--- a/src/mwparserfromhell/nodes/tag.py
+++ b/src/mwparserfromhell/nodes/tag.py
@@ -19,11 +19,16 @@
# SOFTWARE.
+from typing import TYPE_CHECKING, Any, Callable, Optional, List, Generator
+
from ._base import Node
from .extras import Attribute
from ..definitions import is_visible
from ..utils import parse_anything
+if TYPE_CHECKING:
+ from ..wikicode import Wikicode
+
__all__ = ["Tag"]
@@ -32,19 +37,22 @@ class Tag(Node):
def __init__(
self,
- tag,
- contents=None,
- attrs=None,
- wiki_markup=None,
- self_closing=False,
- invalid=False,
- implicit=False,
- padding="",
- closing_tag=None,
- wiki_style_separator=None,
- closing_wiki_markup=None,
+ tag: Any,
+ contents: Any = None,
+ attrs: Optional[List[Attribute]] = None,
+ wiki_markup: Optional[str] = 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,
):
super().__init__()
+ self._attrs: List[Attribute]
+ self._closing_wiki_markup: Optional[str]
+
self.tag = tag
self.contents = contents
self._attrs = attrs if attrs else []
@@ -60,7 +68,7 @@ class Tag(Node):
if closing_wiki_markup is not None:
self.closing_wiki_markup = closing_wiki_markup
- def __str__(self):
+ def __str__(self) -> str:
if self.wiki_markup:
if self.attributes:
attrs = "".join([str(attr) for attr in self.attributes])
@@ -90,7 +98,7 @@ class Tag(Node):
result += "" + str(self.closing_tag) + ">"
return result
- def __children__(self):
+ def __children__(self) -> Generator["Wikicode"]:
if not self.wiki_markup:
yield self.tag
for attr in self.attributes:
@@ -102,12 +110,17 @@ class Tag(Node):
if not self.wiki_markup and self.closing_tag:
yield self.closing_tag
- def __strip__(self, **kwargs):
- if self.contents and is_visible(self.tag):
+ def __strip__(self, **kwargs: Any) -> Optional[str]:
+ if self.contents and is_visible(str(self.tag)):
return self.contents.strip_code(**kwargs)
return None
- def __showtree__(self, write, get, mark):
+ def __showtree__(
+ self,
+ write: Callable[[str], None],
+ get: Callable[["Wikicode"], None],
+ mark: Callable[[], None],
+ ) -> None:
write("" if self.invalid else "<")
get(self.tag)
for attr in self.attributes:
@@ -127,17 +140,25 @@ class Tag(Node):
write(">")
@property
- def tag(self):
+ def tag(self) -> "Wikicode":
"""The tag itself, as a :class:`.Wikicode` object."""
return self._tag
+ @tag.setter
+ def tag(self, value: Any) -> None:
+ self._tag = self._closing_tag = parse_anything(value)
+
@property
- def contents(self):
+ def contents(self) -> "Wikicode":
"""The contents of the tag, as a :class:`.Wikicode` object."""
return self._contents
+ @contents.setter
+ def contents(self, value: Any) -> None:
+ self._contents = parse_anything(value)
+
@property
- def attributes(self):
+ def attributes(self) -> List[Attribute]:
"""The list of attributes affecting the tag.
Each attribute is an instance of :class:`.Attribute`.
@@ -145,7 +166,7 @@ class Tag(Node):
return self._attrs
@property
- def wiki_markup(self):
+ def wiki_markup(self) -> Optional[str]:
"""The wikified version of a tag to show instead of HTML.
If set to a value, this will be displayed instead of the brackets.
@@ -154,13 +175,23 @@ class Tag(Node):
"""
return self._wiki_markup
+ @wiki_markup.setter
+ def wiki_markup(self, value: Optional[str]) -> 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
+
@property
- def self_closing(self):
+ def self_closing(self) -> bool:
"""Whether the tag is self-closing with no content (like ``
``)."""
return self._self_closing
+ @self_closing.setter
+ def self_closing(self, value: bool) -> None:
+ self._self_closing = bool(value)
+
@property
- def invalid(self):
+ def invalid(self) -> bool:
"""Whether the tag starts with a backslash after the opening bracket.
This makes the tag look like a lone close tag. It is technically
@@ -170,8 +201,12 @@ class Tag(Node):
"""
return self._invalid
+ @invalid.setter
+ def invalid(self, value: bool) -> None:
+ self._invalid = bool(value)
+
@property
- def implicit(self):
+ def implicit(self) -> bool:
"""Whether the tag is implicitly self-closing, with no ending slash.
This is only possible for specific "single" tags like ``
`` and
@@ -180,13 +215,27 @@ class Tag(Node):
"""
return self._implicit
+ @implicit.setter
+ def implicit(self, value: bool) -> None:
+ self._implicit = bool(value)
+
@property
- def padding(self):
+ def padding(self) -> str:
"""Spacing to insert before the first closing ``>``."""
return self._padding
+ @padding.setter
+ def padding(self, value: str) -> None:
+ if not value:
+ self._padding = ""
+ else:
+ value = str(value)
+ if not value.isspace():
+ raise ValueError("padding must be entirely whitespace")
+ self._padding = value
+
@property
- def closing_tag(self):
+ def closing_tag(self) -> "Wikicode":
"""The closing tag, as a :class:`.Wikicode` object.
This will usually equal :attr:`tag`, unless there is additional
@@ -194,76 +243,40 @@ class Tag(Node):
"""
return self._closing_tag
+ @closing_tag.setter
+ def closing_tag(self, value: Any) -> None:
+ self._closing_tag = parse_anything(value)
+
@property
- def wiki_style_separator(self):
+ def wiki_style_separator(self) -> Optional[str]:
"""The separator between the padding and content in a wiki markup tag.
Essentially the wiki equivalent of the TagCloseOpen.
"""
return self._wiki_style_separator
+ @wiki_style_separator.setter
+ def wiki_style_separator(self, value: Optional[str]) -> None:
+ self._wiki_style_separator = str(value) if value else None
+
@property
- def closing_wiki_markup(self):
+ def closing_wiki_markup(self) -> Optional[str]:
"""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
- brackets. If tag is :attr:`self_closing` is ``True`` then this is not
- displayed. If :attr:`wiki_markup` is set and this has not been set, this
- is set to the value of :attr:`wiki_markup`. If this has been set and
+ brackets. If the tag is :attr:`self_closing`, this is not displayed.
+ If :attr:`wiki_markup` is set and this has not been set, this is set
+ to the value of :attr:`wiki_markup`. If this has been set and
:attr:`wiki_markup` is set to a ``False`` value, this is set to
``None``.
"""
return self._closing_wiki_markup
- @tag.setter
- def tag(self, value):
- self._tag = self._closing_tag = parse_anything(value)
-
- @contents.setter
- def contents(self, value):
- self._contents = parse_anything(value)
-
- @wiki_markup.setter
- def wiki_markup(self, value):
- 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
-
- @self_closing.setter
- def self_closing(self, value):
- self._self_closing = bool(value)
-
- @invalid.setter
- def invalid(self, value):
- self._invalid = bool(value)
-
- @implicit.setter
- def implicit(self, value):
- self._implicit = bool(value)
-
- @padding.setter
- def padding(self, value):
- if not value:
- self._padding = ""
- else:
- value = str(value)
- if not value.isspace():
- raise ValueError("padding must be entirely whitespace")
- self._padding = value
-
- @closing_tag.setter
- def closing_tag(self, value):
- self._closing_tag = parse_anything(value)
-
- @wiki_style_separator.setter
- def wiki_style_separator(self, value):
- self._wiki_style_separator = str(value) if value else None
-
@closing_wiki_markup.setter
- def closing_wiki_markup(self, value):
+ def closing_wiki_markup(self, value: Optional[str]) -> None:
self._closing_wiki_markup = str(value) if value else None
- def has(self, name):
+ def has(self, name: str) -> bool:
"""Return whether any attribute in the tag has the given *name*.
Note that a tag may have multiple attributes with the same name, but
@@ -274,7 +287,7 @@ class Tag(Node):
return True
return False
- def get(self, name):
+ def get(self, name: str) -> Attribute:
"""Get the attribute with the given *name*.
The returned object is a :class:`.Attribute` instance. Raises
@@ -289,13 +302,13 @@ class Tag(Node):
def add(
self,
- name,
- value=None,
- quotes='"',
- pad_first=" ",
- pad_before_eq="",
- pad_after_eq="",
- ):
+ name: Any,
+ value: Any = None,
+ quotes: Optional[str] = '"',
+ pad_first: str = " ",
+ pad_before_eq: str = "",
+ pad_after_eq: str = "",
+ ) -> Attribute:
"""Add an attribute with the given *name* and *value*.
*name* and *value* can be anything parsable by
@@ -318,7 +331,7 @@ class Tag(Node):
self.attributes.append(attr)
return attr
- def remove(self, name):
+ def remove(self, name: str) -> None:
"""Remove all attributes with the given *name*.
Raises :exc:`ValueError` if none were found.