Ver a proveniência

Add type hints: mwparserfromhell.nodes.template

pull/338/head
Jakub Klinkovský há 1 ano
ascendente
cometimento
907ee6de6a
1 ficheiros alterados com 59 adições e 34 eliminações
  1. +59
    -34
      src/mwparserfromhell/nodes/template.py

+ 59
- 34
src/mwparserfromhell/nodes/template.py Ver ficheiro

@@ -19,6 +19,18 @@
# SOFTWARE. # SOFTWARE.
from collections import defaultdict from collections import defaultdict
import re import re
from typing import (
TYPE_CHECKING,
Any,
Optional,
Union,
List,
Dict,
Callable,
Generator,
Mapping,
cast,
)


from ._base import Node from ._base import Node
from .html_entity import HTMLEntity from .html_entity import HTMLEntity
@@ -26,6 +38,9 @@ from .text import Text
from .extras import Parameter from .extras import Parameter
from ..utils import parse_anything from ..utils import parse_anything


if TYPE_CHECKING:
from ..wikicode import Wikicode

__all__ = ["Template"] __all__ = ["Template"]


FLAGS = re.DOTALL | re.UNICODE FLAGS = re.DOTALL | re.UNICODE
@@ -36,34 +51,36 @@ _UNSET = object()
class Template(Node): class Template(Node):
"""Represents a template in wikicode, like ``{{foo}}``.""" """Represents a template in wikicode, like ``{{foo}}``."""


def __init__(self, name, params=None):
def __init__(self, name: Any, params: Optional[List[Parameter]] = None):
super().__init__() super().__init__()
self.name = name self.name = name
if params:
self._params = params
else:
self._params = []
self._params: List[Parameter] = params or []


def __str__(self):
def __str__(self) -> str:
if self.params: if self.params:
params = "|".join([str(param) for param in self.params]) params = "|".join([str(param) for param in self.params])
return "{{" + str(self.name) + "|" + params + "}}" return "{{" + str(self.name) + "|" + params + "}}"
return "{{" + str(self.name) + "}}" return "{{" + str(self.name) + "}}"


def __children__(self):
def __children__(self) -> Generator["Wikicode"]:
yield self.name yield self.name
for param in self.params: for param in self.params:
if param.showkey: if param.showkey:
yield param.name yield param.name
yield param.value yield param.value


def __strip__(self, **kwargs):
def __strip__(self, **kwargs: Any) -> Optional[str]:
if kwargs.get("keep_template_params"): if kwargs.get("keep_template_params"):
parts = [param.value.strip_code(**kwargs) for param in self.params] parts = [param.value.strip_code(**kwargs) for param in self.params]
return " ".join(part for part in parts if part) return " ".join(part for part in parts if part)
return None return None


def __showtree__(self, write, get, mark):
def __showtree__(
self,
write: Callable[[str], None],
get: Callable[["Wikicode"], None],
mark: Callable[[], None],
) -> None:
write("{{") write("{{")
get(self.name) get(self.name)
for param in self.params: for param in self.params:
@@ -76,7 +93,7 @@ class Template(Node):
write("}}") write("}}")


@staticmethod @staticmethod
def _surface_escape(code, char):
def _surface_escape(code: "Wikicode", char: str) -> None:
"""Return *code* with *char* escaped as an HTML entity. """Return *code* with *char* escaped as an HTML entity.


The main use of this is to escape pipes (``|``) or equal signs (``=``) The main use of this is to escape pipes (``|``) or equal signs (``=``)
@@ -89,7 +106,7 @@ class Template(Node):
code.replace(node, node.replace(char, replacement), False) code.replace(node, node.replace(char, replacement), False)


@staticmethod @staticmethod
def _select_theory(theories):
def _select_theory(theories: Dict[str, int]) -> Optional[str]:
"""Return the most likely spacing convention given different options. """Return the most likely spacing convention given different options.


Given a dictionary of convention options as keys and their occurrence Given a dictionary of convention options as keys and their occurrence
@@ -105,7 +122,7 @@ class Template(Node):
return None return None


@staticmethod @staticmethod
def _blank_param_value(value):
def _blank_param_value(value: "Wikicode") -> None:
"""Remove the content from *value* while keeping its whitespace. """Remove the content from *value* while keeping its whitespace.


Replace *value*\\ 's nodes with two text nodes, the first containing Replace *value*\\ 's nodes with two text nodes, the first containing
@@ -120,15 +137,17 @@ class Template(Node):
before, after = match.group(1), match.group(2) before, after = match.group(1), match.group(2)
value.nodes = [Text(before), Text(after)] value.nodes = [Text(before), Text(after)]


def _get_spacing_conventions(self, use_names):
def _get_spacing_conventions(
self, use_names: bool
) -> tuple[Optional[str], Optional[str]]:
"""Try to determine the whitespace conventions for parameters. """Try to determine the whitespace conventions for parameters.


This will examine the existing parameters and use This will examine the existing parameters and use
:meth:`_select_theory` to determine if there are any preferred styles :meth:`_select_theory` to determine if there are any preferred styles
for how much whitespace to put before or after the value. for how much whitespace to put before or after the value.
""" """
before_theories = defaultdict(lambda: 0)
after_theories = defaultdict(lambda: 0)
before_theories: defaultdict[str, int] = defaultdict(lambda: 0)
after_theories: defaultdict[str, int] = defaultdict(lambda: 0)
for param in self.params: for param in self.params:
if not param.showkey: if not param.showkey:
continue continue
@@ -150,14 +169,14 @@ class Template(Node):
after = self._select_theory(after_theories) after = self._select_theory(after_theories)
return before, after return before, after


def _fix_dependendent_params(self, i):
def _fix_dependendent_params(self, i: int) -> None:
"""Unhide keys if necessary after removing the param at index *i*.""" """Unhide keys if necessary after removing the param at index *i*."""
if not self.params[i].showkey: if not self.params[i].showkey:
for param in self.params[i + 1 :]: for param in self.params[i + 1 :]:
if not param.showkey: if not param.showkey:
param.showkey = True param.showkey = True


def _remove_exact(self, needle, keep_field):
def _remove_exact(self, needle: Parameter, keep_field: bool) -> None:
"""Remove a specific parameter, *needle*, from the template.""" """Remove a specific parameter, *needle*, from the template."""
for i, param in enumerate(self.params): for i, param in enumerate(self.params):
if param is needle: if param is needle:
@@ -169,7 +188,7 @@ class Template(Node):
return return
raise ValueError(needle) raise ValueError(needle)


def _should_remove(self, i, name):
def _should_remove(self, i: int, name: str) -> bool:
"""Look ahead for a parameter with the same name, but hidden. """Look ahead for a parameter with the same name, but hidden.


If one exists, we should remove the given one rather than blanking it. If one exists, we should remove the given one rather than blanking it.
@@ -183,20 +202,20 @@ class Template(Node):
return False return False


@property @property
def name(self):
def name(self) -> "Wikicode":
"""The name of the template, as a :class:`.Wikicode` object.""" """The name of the template, as a :class:`.Wikicode` object."""
return self._name return self._name


@name.setter
def name(self, value: Any) -> None:
self._name = parse_anything(value)

@property @property
def params(self):
def params(self) -> List[Parameter]:
"""The list of parameters contained within the template.""" """The list of parameters contained within the template."""
return self._params return self._params


@name.setter
def name(self, value):
self._name = parse_anything(value)

def has(self, name, ignore_empty=False):
def has(self, name: Union[str, Any], ignore_empty: bool = False) -> bool:
"""Return ``True`` if any parameter in the template is named *name*. """Return ``True`` if any parameter in the template is named *name*.


With *ignore_empty*, ``False`` will be returned even if the template With *ignore_empty*, ``False`` will be returned even if the template
@@ -212,11 +231,11 @@ class Template(Node):
return True return True
return False return False


def has_param(self, name, ignore_empty=False):
def has_param(self, name: Union[str, Any], ignore_empty: bool = False) -> bool:
"""Alias for :meth:`has`.""" """Alias for :meth:`has`."""
return self.has(name, ignore_empty) return self.has(name, ignore_empty)


def get(self, name, default=_UNSET):
def get(self, name: Union[str, Any], default: Any = _UNSET) -> Union[Parameter, Any]:
"""Get the parameter whose name is *name*. """Get the parameter whose name is *name*.


The returned object is a :class:`.Parameter` instance. Raises The returned object is a :class:`.Parameter` instance. Raises
@@ -233,12 +252,18 @@ class Template(Node):
raise ValueError(name) raise ValueError(name)
return default return default


def __getitem__(self, name):
def __getitem__(self, name: Union[str, Any]) -> Parameter:
return self.get(name) return self.get(name)


def add( def add(
self, name, value, showkey=None, before=None, after=None, preserve_spacing=True
):
self,
name: Any,
value: Any,
showkey: Optional[bool] = None,
before: Optional[Union[Parameter, str]] = None,
after: Optional[Union[Parameter, str]] = None,
preserve_spacing: bool = True,
) -> Parameter:
"""Add a parameter to the template with a given *name* and *value*. """Add a parameter to the template with a given *name* and *value*.


*name* and *value* can be anything parsable by *name* and *value* can be anything parsable by
@@ -329,7 +354,7 @@ class Template(Node):
self.params.append(param) self.params.append(param)
return param return param


def update(self, params, **kwargs):
def update(self, params: Mapping[Any, Any], **kwargs: Any) -> None:
"""Update the template with multiple parameters at once. """Update the template with multiple parameters at once.
Args: Args:
params: A dictionary mapping parameter names to values. params: A dictionary mapping parameter names to values.
@@ -340,10 +365,10 @@ class Template(Node):
for name, value in params.items(): for name, value in params.items():
self.add(name, value, **kwargs) self.add(name, value, **kwargs)


def __setitem__(self, name, value):
def __setitem__(self, name: Any, value: Any) -> Parameter:
return self.add(name, value) return self.add(name, value)


def remove(self, param, keep_field=False):
def remove(self, param: Union[Parameter, str], keep_field: bool = False) -> None:
"""Remove a parameter from the template, identified by *param*. """Remove a parameter from the template, identified by *param*.


If *param* is a :class:`.Parameter` object, it will be matched exactly, If *param* is a :class:`.Parameter` object, it will be matched exactly,
@@ -390,5 +415,5 @@ class Template(Node):
for i in reversed(to_remove): for i in reversed(to_remove):
self.params.pop(i) self.params.pop(i)


def __delitem__(self, param):
def __delitem__(self, param: Union[Parameter, str]) -> None:
return self.remove(param) return self.remove(param)

Carregando…
Cancelar
Guardar