瀏覽代碼

Add type hints: mwparserfromhell.nodes.template

pull/338/head
Jakub Klinkovský 1 年之前
父節點
當前提交
907ee6de6a
共有 1 個檔案被更改,包括 59 行新增 和 34 行删除
  1. +59
    -34
      src/mwparserfromhell/nodes/template.py

+ 59
- 34
src/mwparserfromhell/nodes/template.py 查看文件

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

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

if TYPE_CHECKING:
from ..wikicode import Wikicode

__all__ = ["Template"]

FLAGS = re.DOTALL | re.UNICODE
@@ -36,34 +51,36 @@ _UNSET = object()
class Template(Node):
"""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__()
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:
params = "|".join([str(param) for param in self.params])
return "{{" + str(self.name) + "|" + params + "}}"
return "{{" + str(self.name) + "}}"

def __children__(self):
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):
def __strip__(self, **kwargs: Any) -> Optional[str]:
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)
return None

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

@staticmethod
def _surface_escape(code, char):
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 (``=``)
@@ -89,7 +106,7 @@ class Template(Node):
code.replace(node, node.replace(char, replacement), False)

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

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

@staticmethod
def _blank_param_value(value):
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
@@ -120,15 +137,17 @@ class Template(Node):
before, after = match.group(1), match.group(2)
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.

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(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:
if not param.showkey:
continue
@@ -150,14 +169,14 @@ class Template(Node):
after = self._select_theory(after_theories)
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*."""
if not self.params[i].showkey:
for param in self.params[i + 1 :]:
if not param.showkey:
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."""
for i, param in enumerate(self.params):
if param is needle:
@@ -169,7 +188,7 @@ class Template(Node):
return
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.

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

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

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

@property
def params(self):
def params(self) -> List[Parameter]:
"""The list of parameters contained within the template."""
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*.

With *ignore_empty*, ``False`` will be returned even if the template
@@ -212,11 +231,11 @@ class Template(Node):
return True
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`."""
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*.

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

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

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*.

*name* and *value* can be anything parsable by
@@ -329,7 +354,7 @@ class Template(Node):
self.params.append(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.
Args:
params: A dictionary mapping parameter names to values.
@@ -340,10 +365,10 @@ class Template(Node):
for name, value in params.items():
self.add(name, value, **kwargs)

def __setitem__(self, name, value):
def __setitem__(self, name: Any, value: Any) -> Parameter:
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*.

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):
self.params.pop(i)

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

Loading…
取消
儲存