Skip to content

Commit

Permalink
use registry for atom xml attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
cleder committed Mar 15, 2024
1 parent 2acf5be commit ed7160e
Show file tree
Hide file tree
Showing 2 changed files with 219 additions and 51 deletions.
112 changes: 65 additions & 47 deletions fastkml/atom.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,20 @@
"""

import logging
from typing import Any
from typing import Dict
from typing import Optional

from fastkml import config
from fastkml.base import _XMLObject
from fastkml.config import ATOMNS as NS
from fastkml.enums import Verbosity
from fastkml.helpers import attribute_int_kwarg
from fastkml.helpers import attribute_text_kwarg
from fastkml.helpers import int_attribute
from fastkml.helpers import subelement_text_kwarg
from fastkml.helpers import text_attribute
from fastkml.helpers import text_subelement
from fastkml.registry import RegistryItem
from fastkml.registry import registry
from fastkml.types import Element

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -141,51 +142,68 @@ def __eq__(self, other: object) -> bool:
and self.length == other.length
)

def etree_element(
self,
precision: Optional[int] = None,
verbosity: Verbosity = Verbosity.normal,
) -> Element:
element = super().etree_element(precision=precision, verbosity=verbosity)
if self.href:
element.set("href", self.href)
else:
logger.warning("required attribute href missing")
if self.rel:
element.set("rel", self.rel)
if self.type:
element.set("type", self.type)
if self.hreflang:
element.set("hreflang", self.hreflang)
if self.title:
element.set("title", self.title)
if self.length:
element.set("length", str(self.length))
return element

@classmethod
def _get_kwargs(
cls,
*,
ns: str,
name_spaces: Optional[Dict[str, str]] = None,
element: Element,
strict: bool,
) -> Dict[str, Any]:
kwargs = super()._get_kwargs(
ns=ns,
name_spaces=name_spaces,
element=element,
strict=strict,
)
kwargs["href"] = element.get("href")
kwargs["rel"] = element.get("rel")
kwargs["type"] = element.get("type")
kwargs["hreflang"] = element.get("hreflang")
kwargs["title"] = element.get("title")
length = element.get("length")
kwargs["length"] = int(length) if length and length.strip() else None
return kwargs
registry.register(
Link,
item=RegistryItem(
attr_name="href",
node_name="href",
classes=(str,),
get_kwarg=attribute_text_kwarg,
set_element=text_attribute,
),
)
registry.register(
Link,
item=RegistryItem(
attr_name="rel",
node_name="rel",
classes=(str,),
get_kwarg=attribute_text_kwarg,
set_element=text_attribute,
),
)
registry.register(
Link,
item=RegistryItem(
attr_name="type",
node_name="type",
classes=(str,),
get_kwarg=attribute_text_kwarg,
set_element=text_attribute,
),
)
registry.register(
Link,
item=RegistryItem(
attr_name="hreflang",
node_name="hreflang",
classes=(str,),
get_kwarg=attribute_text_kwarg,
set_element=text_attribute,
),
)

registry.register(
Link,
item=RegistryItem(
attr_name="title",
node_name="title",
classes=(str,),
get_kwarg=attribute_text_kwarg,
set_element=text_attribute,
),
)
registry.register(
Link,
item=RegistryItem(
attr_name="length",
node_name="length",
classes=(int,),
get_kwarg=attribute_int_kwarg,
set_element=int_attribute,
),
)


class _Person(_AtomObject):
Expand Down
158 changes: 154 additions & 4 deletions fastkml/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,23 @@ def handle_error(
node: Element,
expected: str,
) -> None:
"""Handle an error."""
"""
Handle an error.
Args:
----
error (Exception): The exception that occurred.
strict (bool): A flag indicating whether to raise an exception or log a warning.
element (Element): The XML element being parsed.
node (Element): The XML node that caused the error.
expected (str): The expected format or value.
Raises:
------
KMLParseError: If `strict` is True, the function raises a `KMLParseError` with
the error message.
"""
serialized_element = config.etree.tostring( # type: ignore[attr-defined]
element,
encoding="UTF-8",
Expand Down Expand Up @@ -71,7 +87,23 @@ def text_subelement(
precision: Optional[int],
verbosity: Optional[Verbosity],
) -> None:
"""Set the value of an attribute from a subelement with a text node."""
"""
Set the value of an attribute from a subelement with a text node.
Args:
----
obj (_XMLObject): The object from which to retrieve the attribute value.
element (Element): The parent element to add the subelement to.
attr_name (str): The name of the attribute to retrieve the value from.
node_name (str): The name of the subelement to create.
precision (Optional[int]): The precision of the attribute value.
verbosity (Optional[Verbosity]): The verbosity level.
Returns:
-------
None
"""
if getattr(obj, attr_name, None):
subelement = config.etree.SubElement( # type: ignore[attr-defined]
element,
Expand All @@ -80,6 +112,36 @@ def text_subelement(
subelement.text = getattr(obj, attr_name)


def text_attribute(
obj: _XMLObject,
*,
element: Element,
attr_name: str,
node_name: str,
precision: Optional[int],
verbosity: Optional[Verbosity],
) -> None:
"""
Set the value of an attribute from a subelement with a text node.
Args:
----
obj (_XMLObject): The object from which to retrieve the attribute value.
element (Element): The parent element to add the subelement to.
attr_name (str): The name of the attribute to retrieve the value from.
node_name (str): The name of the attribute to be set.
precision (Optional[int]): The precision of the attribute value.
verbosity (Optional[Verbosity]): The verbosity level.
Returns:
-------
None
"""
if getattr(obj, attr_name, None):
element.set(node_name, getattr(obj, attr_name))


def bool_subelement(
obj: _XMLObject,
*,
Expand All @@ -89,7 +151,23 @@ def bool_subelement(
precision: Optional[int],
verbosity: Optional[Verbosity],
) -> None:
"""Set the value of an attribute from a subelement with a text node."""
"""
Set the value of an attribute from a subelement with a text node.
Args:
----
obj (_XMLObject): The object from which to retrieve the attribute value.
element (Element): The parent element to add the subelement to.
attr_name (str): The name of the attribute to retrieve the value from.
node_name (str): The name of the subelement to create.
precision (Optional[int]): The precision of the attribute value.
verbosity (Optional[Verbosity]): The verbosity level.
Returns:
-------
None
"""
if getattr(obj, attr_name, None) is not None:
subelement = config.etree.SubElement( # type: ignore[attr-defined]
element,
Expand All @@ -107,7 +185,23 @@ def int_subelement(
precision: Optional[int],
verbosity: Optional[Verbosity],
) -> None:
"""Set the value of an attribute from a subelement with a text node."""
"""
Set the value of an attribute from a subelement with a text node.
Args:
----
obj (_XMLObject): The object from which to retrieve the attribute value.
element (Element): The parent element to add the subelement to.
attr_name (str): The name of the attribute to retrieve the value from.
node_name (str): The name of the subelement to create.
precision (Optional[int]): The precision of the attribute value.
verbosity (Optional[Verbosity]): The verbosity level.
Returns:
-------
None: This function does not return anything.
"""
if getattr(obj, attr_name, None) is not None:
subelement = config.etree.SubElement( # type: ignore[attr-defined]
element,
Expand All @@ -116,6 +210,36 @@ def int_subelement(
subelement.text = str(getattr(obj, attr_name))


def int_attribute(
obj: _XMLObject,
*,
element: Element,
attr_name: str,
node_name: str,
precision: Optional[int],
verbosity: Optional[Verbosity],
) -> None:
"""
Set the value of an attribute.
Args:
----
obj (_XMLObject): The object from which to retrieve the attribute value.
element (Element): The parent element to add the subelement to.
attr_name (str): The name of the attribute to retrieve the value from.
node_name (str): The name of the attribute to be set.
precision (Optional[int]): The precision of the attribute value.
verbosity (Optional[Verbosity]): The verbosity level.
Returns:
-------
None: This function does not return anything.
"""
if getattr(obj, attr_name, None) is not None:
element.set(node_name, str(getattr(obj, attr_name)))


def float_subelement(
obj: _XMLObject,
*,
Expand Down Expand Up @@ -203,6 +327,19 @@ def subelement_text_kwarg(
return {kwarg: node.text.strip()} if node.text and node.text.strip() else {}


def attribute_text_kwarg(
*,
element: Element,
ns: str,
name_spaces: Dict[str, str],
node_name: str,
kwarg: str,
classes: Tuple[known_types, ...],
strict: bool,
) -> Dict[str, str]:
return {kwarg: element.get(node_name)} if element.get(node_name) else {}


def subelement_bool_kwarg(
*,
element: Element,
Expand Down Expand Up @@ -265,6 +402,19 @@ def subelement_int_kwarg(
return {}


def attribute_int_kwarg(
*,
element: Element,
ns: str,
name_spaces: Dict[str, str],
node_name: str,
kwarg: str,
classes: Tuple[known_types, ...],
strict: bool,
) -> Dict[str, int]:
return {kwarg: int(element.get(node_name))} if element.get(node_name) else {}


def subelement_float_kwarg(
*,
element: Element,
Expand Down

0 comments on commit ed7160e

Please sign in to comment.