From 99da9e2c29c8384ab40ea2a25437e62e3693d552 Mon Sep 17 00:00:00 2001 From: Calvin Date: Fri, 6 Dec 2024 20:30:27 +0100 Subject: [PATCH 1/5] updated deps --- pyproject.toml | 14 +++++++------- tox.ini | 16 ++++++++-------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index df75bc5..42e0fbb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["setuptools == 70.2.0", "setuptools_scm[toml] == 8.1.0"] +requires = ["setuptools == 75.6.0", "setuptools_scm[toml] == 8.1.0"] build-backend = "setuptools.build_meta" [project] @@ -8,7 +8,7 @@ authors = [{name = "c3kay"}] description = "RSS feed generator for official game news from Hoyolab." readme = "README.md" license = {text = "MIT License"} -requires-python = ">=3.8" +requires-python = ">=3.9" keywords = [ "hoyolab", "rss", @@ -36,17 +36,17 @@ classifiers = [ dependencies = [ "aiohttp == 3.9.5", "aiofiles == 24.1.0", - "pydantic == 1.10.13, < 2", + "pydantic >= 1.10.0, < 2", 'tomli == 2.0.1 ; python_version < "3.11"' ] dynamic = ["version"] [project.optional-dependencies] dev = [ - "tox == 4.11.4", - "pytest == 8.2.2", - "pytest-asyncio == 0.23.7", - "pytest-cov == 5.0.0", + "tox == 4.23.2", + "pytest == 8.3.4", + "pytest-asyncio == 0.24.0", + "pytest-cov == 6.0.0", "pytest-mock == 3.14.0", "atoma == 0.0.17", "langdetect == 1.0.9" diff --git a/tox.ini b/tox.ini index ddfb494..3e0d30e 100644 --- a/tox.ini +++ b/tox.ini @@ -12,34 +12,34 @@ python = [testenv] deps = - pytest == 8.2.2 - pytest-asyncio == 0.23.7 - pytest-cov == 5.0.0 + pytest == 8.3.4 + pytest-asyncio == 0.24.0 + pytest-cov == 6.0.0 pytest-mock == 3.14.0 - coverage[toml] == 7.5.4 + coverage[toml] == 7.6.9 atoma == 0.0.17 langdetect == 1.0.9 commands = pytest {posargs} [testenv:type] deps = - mypy == 1.10.1 + mypy == 1.13.0 {[testenv]deps} commands = mypy --install-types --non-interactive {posargs} [testenv:clean] skip_install = true -deps = coverage[toml] == 7.4.0 +deps = coverage[toml] == 7.6.9 commands = coverage erase [testenv:black] skip_install = true -deps = black == 24.4.2 +deps = black == 24.10.0 commands = black src tests {posargs} [testenv:flake] skip_install = true -deps = flake8 == 7.1.0 +deps = flake8 == 7.1.1 commands = flake8 {posargs} From ea5a97f88f3880303e308190f2e19e28a460ceaa Mon Sep 17 00:00:00 2001 From: Calvin Date: Fri, 6 Dec 2024 21:51:06 +0100 Subject: [PATCH 2/5] added summary field to feed item --- src/hoyolabrssfeeds/hoyolab.py | 1 + src/hoyolabrssfeeds/loaders.py | 152 ++++++++++++++++----------------- src/hoyolabrssfeeds/models.py | 1 + src/hoyolabrssfeeds/writers.py | 3 + 4 files changed, 80 insertions(+), 77 deletions(-) diff --git a/src/hoyolabrssfeeds/hoyolab.py b/src/hoyolabrssfeeds/hoyolab.py index f2025e0..531b04c 100644 --- a/src/hoyolabrssfeeds/hoyolab.py +++ b/src/hoyolabrssfeeds/hoyolab.py @@ -205,6 +205,7 @@ async def get_feed_item( "title": post["post"]["subject"], "author": post["user"]["nickname"], "content": post["post"]["content"], + "summary": post["post"]["desc"], "category": post["post"]["official_type"], "published": post["post"]["created_at"], } diff --git a/src/hoyolabrssfeeds/loaders.py b/src/hoyolabrssfeeds/loaders.py index d35e752..9b3aadb 100644 --- a/src/hoyolabrssfeeds/loaders.py +++ b/src/hoyolabrssfeeds/loaders.py @@ -81,40 +81,39 @@ class JSONFeedFileLoader(AbstractFeedFileLoader): async def get_feed_items(self) -> List[FeedItem]: """Returns feed items of JSON-Feed if feed exists.""" - if self.config.path.exists(): - feed_items = [] - feed = await self._load_from_file() + if not self.config.path.exists(): + return [] - try: - for item in feed["items"]: - category = FeedItemCategory.from_str(item["tags"][0]) - - item_dict = { - "id": item["id"], - "title": item["title"], - "author": item["authors"][0]["name"], - "content": item["content_html"], - "category": category, - "published": item["date_published"], - } - - if "date_modified" in item: - item_dict["updated"] = item["date_modified"] - - if "image" in item: - item_dict["image"] = item["image"] - - feed_items.append(item_dict) - except KeyError as err: - raise FeedFormatError( - "Could not find required key in JSON feed!" - ) from err - except ValueError as err: - raise FeedFormatError("Could not load JSON feed items!") from err + feed_items = [] + feed = await self._load_from_file() - return pydantic.parse_obj_as(List[FeedItem], feed_items) - else: - return [] + try: + for item in feed["items"]: + category = FeedItemCategory.from_str(item["tags"][0]) + + item_dict = { + "id": item["id"], + "title": item["title"], + "author": item["authors"][0]["name"], + "content": item["content_html"], + "summary": item["summary"], + "category": category, + "published": item["date_published"], + } + + if "date_modified" in item: + item_dict["updated"] = item["date_modified"] + + if "image" in item: + item_dict["image"] = item["image"] + + feed_items.append(item_dict) + except KeyError as err: + raise FeedFormatError("Could not find required key in JSON feed!") from err + except ValueError as err: + raise FeedFormatError("Could not load JSON feed items!") from err + + return pydantic.parse_obj_as(List[FeedItem], feed_items) async def _load_from_file(self) -> Dict[str, Any]: """Load JSON-Feed from file.""" @@ -140,56 +139,55 @@ class AtomFeedFileLoader(AbstractFeedFileLoader): async def get_feed_items(self) -> List[FeedItem]: """Returns feed items of Atom feed if feed exists.""" - if self.config.path.exists(): - feed_items = [] - root = await self._load_from_file() - - for entry in root.findall("entry"): - id_str = entry.findtext("id") - item_id = id_str.rpartition(":")[2] if id_str is not None else None - - category_node = entry.find("category") - try: - category = ( - FeedItemCategory.from_str(category_node.get("term", default="")) - if category_node is not None - else None - ) - except ValueError as err: - raise FeedFormatError("Could not load Atom feed entries!") from err - - published_str = entry.findtext("published") - published = ( - datetime.fromisoformat(published_str) - if published_str is not None - else None - ) - - updated_str = entry.findtext("updated") - updated = ( - datetime.fromisoformat(updated_str) - if updated_str is not None - else None - ) + if not self.config.path.exists(): + return [] - item_dict = { - "id": item_id, - "title": entry.findtext("title"), - "author": entry.findtext("author/name"), - "content": entry.findtext("content"), - "category": category, - "published": published, - "updated": updated, - } + feed_items = [] + root = await self._load_from_file() - feed_items.append(item_dict) + for entry in root.findall("entry"): + id_str = entry.findtext("id") + item_id = id_str.rpartition(":")[2] if id_str is not None else None + category_node = entry.find("category") try: - return pydantic.parse_obj_as(List[FeedItem], feed_items) - except pydantic.ValidationError as err: + category = ( + FeedItemCategory.from_str(category_node.get("term", default="")) + if category_node is not None + else None + ) + except ValueError as err: raise FeedFormatError("Could not load Atom feed entries!") from err - else: - return [] + + published_str = entry.findtext("published") + published = ( + datetime.fromisoformat(published_str) + if published_str is not None + else None + ) + + updated_str = entry.findtext("updated") + updated = ( + datetime.fromisoformat(updated_str) if updated_str is not None else None + ) + + item_dict = { + "id": item_id, + "title": entry.findtext("title"), + "author": entry.findtext("author/name"), + "content": entry.findtext("content"), + "summary": entry.findtext("summary"), + "category": category, + "published": published, + "updated": updated, + } + + feed_items.append(item_dict) + + try: + return pydantic.parse_obj_as(List[FeedItem], feed_items) + except pydantic.ValidationError as err: + raise FeedFormatError("Could not load Atom feed entries!") from err async def _load_from_file(self) -> ElementTree.Element: """Load Atom feed from file.""" diff --git a/src/hoyolabrssfeeds/models.py b/src/hoyolabrssfeeds/models.py index 35606ad..c98db81 100644 --- a/src/hoyolabrssfeeds/models.py +++ b/src/hoyolabrssfeeds/models.py @@ -104,6 +104,7 @@ class FeedItem(MyBaseModel): title: str author: str content: str + summary: str category: FeedItemCategory published: datetime updated: Optional[datetime] = None diff --git a/src/hoyolabrssfeeds/writers.py b/src/hoyolabrssfeeds/writers.py index 4c36690..392eba5 100644 --- a/src/hoyolabrssfeeds/writers.py +++ b/src/hoyolabrssfeeds/writers.py @@ -95,6 +95,7 @@ def create_json_feed_item(item: FeedItem) -> Dict[str, Any]: "authors": [{"name": item.author}], "tags": [item.category.name.title()], "content_html": item.content, + "summary": item.summary, "date_published": item.published.astimezone().isoformat(), } @@ -211,6 +212,8 @@ def create_atom_feed_entries( item.content ) + ElementTree.SubElement(entry, "summary").text = item.summary + entries.append(entry) return entries From f0ac15e4f5bbcf4b310edd0f3155982b84b1a6fc Mon Sep 17 00:00:00 2001 From: Calvin Date: Fri, 6 Dec 2024 21:51:30 +0100 Subject: [PATCH 3/5] updated tests for new summary field --- tests/conftest.py | 6 ++++++ tests/test_hoyolab.py | 1 + 2 files changed, 7 insertions(+) diff --git a/tests/conftest.py b/tests/conftest.py index 872f551..64345d0 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -165,6 +165,7 @@ def feed_item() -> models.FeedItem: title="Test Article", author="John Doe", content="

Hello World!

", + summary="Hello!", category=models.FeedItemCategory.INFO, published=datetime(2022, 10, 3, 16).astimezone(), updated=datetime(2022, 10, 3, 18).astimezone(), @@ -190,6 +191,7 @@ def json_feed_items(feed_item_list: List[models.FeedItem]) -> Dict[str, Any]: "authors": [{"name": feed_item.author}], "tags": [feed_item.category.name.title()], "content_html": feed_item.content, + "summary": feed_item.summary, "date_published": feed_item.published.astimezone().isoformat(), "date_modified": ( feed_item.updated.astimezone().isoformat() @@ -218,6 +220,7 @@ def atom_feed_entries(feed_item_list: List[models.FeedItem]) -> ElementTree.Elem ElementTree.SubElement(entry, "title").text = feed_item.title ElementTree.SubElement(entry, "content").text = feed_item.content + ElementTree.SubElement(entry, "summary").text = feed_item.summary ElementTree.SubElement( entry, "category", {"term": feed_item.category.name.title()} ) @@ -315,6 +318,9 @@ def validate_hoyolab_post(post: Dict[str, Any], is_full_post: bool) -> None: assert type(post["post"]["content"]) is str assert len(post["post"]["content"]) > 0 + assert type(post["post"]["desc"]) is str + assert len(post["post"]["desc"]) > 0 + assert type(post["post"]["structured_content"]) is str assert len(post["post"]["structured_content"]) > 0 diff --git a/tests/test_hoyolab.py b/tests/test_hoyolab.py index 7a00499..f670574 100644 --- a/tests/test_hoyolab.py +++ b/tests/test_hoyolab.py @@ -144,6 +144,7 @@ async def test_get_feed_item( "post_id": str(feed_item.id), "subject": feed_item.title, "content": feed_item.content, + "desc": feed_item.summary, "official_type": feed_item.category.value, "created_at": int(feed_item.published.timestamp()), }, From 733d63bcf79c9d49aca6d70906e0ee37844aa719 Mon Sep 17 00:00:00 2001 From: Calvin Date: Fri, 6 Dec 2024 21:55:29 +0100 Subject: [PATCH 4/5] updated RELEASENOTES.md --- RELEASENOTES.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 003e1a3..2e16f04 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,8 +1,7 @@ ## Changes -- Added support for python 3.12 - - Support for python 3.8 will be dropped in the next version +- Added a `summary` field for feed items in both Atom and JSON-Feed format (#15) ## Fixes -- Added fix for native hoyolab video posts (#13) +- Updated dependencies From 93269b15daaa3c61abdcd7da036b00fba03dfd44 Mon Sep 17 00:00:00 2001 From: Calvin Date: Sat, 7 Dec 2024 15:29:24 +0100 Subject: [PATCH 5/5] updated build workflow --- .github/workflows/{publish.yaml => build.yaml} | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename .github/workflows/{publish.yaml => build.yaml} (99%) diff --git a/.github/workflows/publish.yaml b/.github/workflows/build.yaml similarity index 99% rename from .github/workflows/publish.yaml rename to .github/workflows/build.yaml index 62702aa..e3acc2b 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/build.yaml @@ -1,4 +1,4 @@ -name: Publish +name: Build on: push: diff --git a/README.md b/README.md index 861f8fe..1e8202c 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![PyPI](https://img.shields.io/pypi/v/hoyolab-rss-feeds)](https://pypi.org/project/hoyolab-rss-feeds/) [![Python Version](https://img.shields.io/pypi/pyversions/hoyolab-rss-feeds)](https://pypi.org/project/hoyolab-rss-feeds/) -[![Tests Status](https://img.shields.io/github/actions/workflow/status/c3kay/hoyolab-rss-feeds/test.yaml?branch=master)](https://github.com/c3kay/hoyolab-rss-feeds/actions/workflows/test.yaml) +[![Tests Status](https://img.shields.io/github/actions/workflow/status/c3kay/hoyolab-rss-feeds/build.yaml)](https://github.com/c3kay/hoyolab-rss-feeds/actions/workflows/build.yaml) [![Codecov](https://img.shields.io/codecov/c/gh/c3kay/hoyolab-rss-feeds/master)](https://app.codecov.io/gh/c3kay/hoyolab-rss-feeds) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) [![Checked with mypy](http://www.mypy-lang.org/static/mypy_badge.svg)](http://mypy-lang.org/)