File: feed_dict_source.py

package info (click to toggle)
python-georss-client 0.19-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 324 kB
  • sloc: python: 1,625; xml: 507; makefile: 3
file content (91 lines) | stat: -rw-r--r-- 2,854 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
"""GeoRSS feed dict source."""

from __future__ import annotations

from typing import Optional

from georss_client.consts import (
    XML_ATTR_HREF,
    XML_CDATA,
    XML_TAG_CONTENT,
    XML_TAG_DESCRIPTION,
    XML_TAG_LINK,
    XML_TAG_SUMMARY,
    XML_TAG_TITLE,
)


class FeedDictSource:
    """Represents a subset of a feed based on a dict."""

    def __init__(self, source: dict):
        """Initialise feed."""
        self._source: dict = source

    def __repr__(self):
        """Return string representation of this feed item."""
        return f"<{self.__class__.__name__}({self.link})>"

    def _attribute(self, names: list[str]) -> Optional:
        """Get an attribute from this feed or feed item."""
        if self._source and names:
            # Try each name, and return the first value that is not None.
            for name in names:
                value = self._source.get(name, None)
                if value:
                    return value
        return None

    def _attribute_with_text(self, names: list[str]) -> Optional:
        """Get an attribute with text from this feed or feed item."""
        value = self._attribute(names)
        if value and isinstance(value, dict) and XML_CDATA in value:
            # <tag attr="/some.uri">Value</tag>
            value = value.get(XML_CDATA)
        return value

    @staticmethod
    def _attribute_in_structure(obj, keys: list[str]) -> Optional:
        """Return the attribute found under the chain of keys."""
        key = keys.pop(0)
        if key in obj:
            return (
                FeedDictSource._attribute_in_structure(obj[key], keys)
                if keys
                else obj[key]
            )
        return None

    @property
    def title(self) -> str | None:
        """Return the title of this feed or feed item."""
        return self._attribute_with_text([XML_TAG_TITLE])

    @property
    def description(self) -> str | None:
        """Return the description of this feed or feed item."""
        return self._attribute_with_text(
            [XML_TAG_DESCRIPTION, XML_TAG_SUMMARY, XML_TAG_CONTENT]
        )

    @property
    def summary(self) -> str | None:
        """Return the summary of this feed or feed item."""
        return self.description

    @property
    def content(self) -> str | None:
        """Return the content of this feed or feed item."""
        return self.description

    @property
    def link(self) -> str | None:
        """Return the link of this feed or feed item."""
        link = self._attribute([XML_TAG_LINK])
        if link and XML_ATTR_HREF in link:
            link = link.get(XML_ATTR_HREF)
        return link

    def get_additional_attribute(self, name: str) -> Optional:
        """Get an additional attribute not provided as property."""
        return self._attribute([name])