| @@ -19,9 +19,14 @@ | |||||
| # SOFTWARE. | # SOFTWARE. | ||||
| from typing import TYPE_CHECKING, Any, Optional | |||||
| from ...string_mixin import StringMixIn | from ...string_mixin import StringMixIn | ||||
| from ...utils import parse_anything | from ...utils import parse_anything | ||||
| if TYPE_CHECKING: | |||||
| from ...wikicode import Wikicode | |||||
| __all__ = ["Attribute"] | __all__ = ["Attribute"] | ||||
| @@ -35,23 +40,28 @@ class Attribute(StringMixIn): | |||||
| def __init__( | def __init__( | ||||
| self, | 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 = "", | |||||
| ): | ): | ||||
| super().__init__() | super().__init__() | ||||
| self._pad_first: str | |||||
| self._pad_before_eq: str | |||||
| self._pad_after_eq: str | |||||
| self.name = name | self.name = name | ||||
| self._quotes = None | |||||
| self._quotes: Optional[str] = None | |||||
| self.value = value | self.value = value | ||||
| self.quotes = quotes | self.quotes = quotes | ||||
| self.pad_first = pad_first | self.pad_first = pad_first | ||||
| self.pad_before_eq = pad_before_eq | self.pad_before_eq = pad_before_eq | ||||
| self.pad_after_eq = pad_after_eq | self.pad_after_eq = pad_after_eq | ||||
| def __str__(self): | |||||
| def __str__(self) -> str: | |||||
| result = self.pad_first + str(self.name) + self.pad_before_eq | result = self.pad_first + str(self.name) + self.pad_before_eq | ||||
| if self.value is not None: | if self.value is not None: | ||||
| result += "=" + self.pad_after_eq | result += "=" + self.pad_after_eq | ||||
| @@ -61,11 +71,11 @@ class Attribute(StringMixIn): | |||||
| return result | return result | ||||
| @staticmethod | @staticmethod | ||||
| def _value_needs_quotes(val): | |||||
| def _value_needs_quotes(value: "Wikicode") -> Optional[str]: | |||||
| """Return valid quotes for the given value, or None if unneeded.""" | """Return valid quotes for the given value, or None if unneeded.""" | ||||
| if not val: | |||||
| if not value: | |||||
| return None | return None | ||||
| val = "".join(str(node) for node in val.filter_text(recursive=False)) | |||||
| val = "".join(str(node) for node in value.filter_text(recursive=False)) | |||||
| if not any(char.isspace() for char in val): | if not any(char.isspace() for char in val): | ||||
| return None | return None | ||||
| if "'" in val and '"' not in val: | if "'" in val and '"' not in val: | ||||
| @@ -74,7 +84,7 @@ class Attribute(StringMixIn): | |||||
| return "'" | return "'" | ||||
| return "\"'" # Either acceptable, " preferred over ' | return "\"'" # Either acceptable, " preferred over ' | ||||
| def _set_padding(self, attr, value): | |||||
| def _set_padding(self, attr: str, value: str) -> None: | |||||
| """Setter for the value of a padding attribute.""" | """Setter for the value of a padding attribute.""" | ||||
| if not value: | if not value: | ||||
| setattr(self, attr, "") | setattr(self, attr, "") | ||||
| @@ -85,49 +95,29 @@ class Attribute(StringMixIn): | |||||
| setattr(self, attr, value) | setattr(self, attr, value) | ||||
| @staticmethod | @staticmethod | ||||
| def coerce_quotes(quotes): | |||||
| def coerce_quotes(quotes: Any) -> Optional[str]: | |||||
| """Coerce a quote type into an acceptable value, or raise an error.""" | """Coerce a quote type into an acceptable value, or raise an error.""" | ||||
| orig, quotes = quotes, str(quotes) if quotes else None | |||||
| if quotes not in [None, '"', "'"]: | |||||
| raise ValueError("{!r} is not a valid quote type".format(orig)) | |||||
| return quotes | |||||
| 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)) | |||||
| return coerced_quotes | |||||
| @property | @property | ||||
| def name(self): | |||||
| def name(self) -> "Wikicode": | |||||
| """The name of the attribute as a :class:`.Wikicode` object.""" | """The name of the attribute 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 value(self): | |||||
| def value(self) -> Optional["Wikicode"]: | |||||
| """The value of the attribute as a :class:`.Wikicode` object.""" | """The value of the attribute as a :class:`.Wikicode` object.""" | ||||
| return self._value | return self._value | ||||
| @property | |||||
| def quotes(self): | |||||
| """How to enclose the attribute value. ``"``, ``'``, or ``None``.""" | |||||
| return self._quotes | |||||
| @property | |||||
| def pad_first(self): | |||||
| """Spacing to insert right before the attribute.""" | |||||
| return self._pad_first | |||||
| @property | |||||
| def pad_before_eq(self): | |||||
| """Spacing to insert right before the equal sign.""" | |||||
| return self._pad_before_eq | |||||
| @property | |||||
| def pad_after_eq(self): | |||||
| """Spacing to insert right after the equal sign.""" | |||||
| return self._pad_after_eq | |||||
| @name.setter | |||||
| def name(self, value): | |||||
| self._name = parse_anything(value) | |||||
| @value.setter | @value.setter | ||||
| def value(self, newval): | |||||
| def value(self, newval: Any) -> None: | |||||
| if newval is None: | if newval is None: | ||||
| self._value = None | self._value = None | ||||
| else: | else: | ||||
| @@ -137,21 +127,41 @@ class Attribute(StringMixIn): | |||||
| self._quotes = quotes[0] | self._quotes = quotes[0] | ||||
| self._value = code | self._value = code | ||||
| @property | |||||
| def quotes(self) -> Optional[str]: | |||||
| """How to enclose the attribute value. ``"``, ``'``, or ``None``.""" | |||||
| return self._quotes | |||||
| @quotes.setter | @quotes.setter | ||||
| def quotes(self, value): | |||||
| def quotes(self, value: Any) -> None: | |||||
| value = self.coerce_quotes(value) | value = self.coerce_quotes(value) | ||||
| if not value and self._value_needs_quotes(self.value): | if not value and self._value_needs_quotes(self.value): | ||||
| raise ValueError("attribute value requires quotes") | raise ValueError("attribute value requires quotes") | ||||
| self._quotes = value | self._quotes = value | ||||
| @property | |||||
| def pad_first(self) -> str: | |||||
| """Spacing to insert right before the attribute.""" | |||||
| return self._pad_first | |||||
| @pad_first.setter | @pad_first.setter | ||||
| def pad_first(self, value): | |||||
| def pad_first(self, value: str) -> None: | |||||
| self._set_padding("_pad_first", value) | self._set_padding("_pad_first", value) | ||||
| @property | |||||
| def pad_before_eq(self) -> str: | |||||
| """Spacing to insert right before the equal sign.""" | |||||
| return self._pad_before_eq | |||||
| @pad_before_eq.setter | @pad_before_eq.setter | ||||
| def pad_before_eq(self, value): | |||||
| def pad_before_eq(self, value: str) -> None: | |||||
| self._set_padding("_pad_before_eq", value) | self._set_padding("_pad_before_eq", value) | ||||
| @property | |||||
| def pad_after_eq(self) -> str: | |||||
| """Spacing to insert right after the equal sign.""" | |||||
| return self._pad_after_eq | |||||
| @pad_after_eq.setter | @pad_after_eq.setter | ||||
| def pad_after_eq(self, value): | |||||
| def pad_after_eq(self, value: str) -> None: | |||||
| self._set_padding("_pad_after_eq", value) | self._set_padding("_pad_after_eq", value) | ||||