From 77a3e9fe96dd76c39a12466f181c4c05fdebfdc6 Mon Sep 17 00:00:00 2001 From: gounux Date: Fri, 26 Apr 2024 09:29:21 +0200 Subject: [PATCH 1/5] Add JSON client for feed and tags --- geotribu_cli/json/__init__.py | 0 geotribu_cli/json/json_client.py | 58 ++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 geotribu_cli/json/__init__.py create mode 100644 geotribu_cli/json/json_client.py diff --git a/geotribu_cli/json/__init__.py b/geotribu_cli/json/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/geotribu_cli/json/json_client.py b/geotribu_cli/json/json_client.py new file mode 100644 index 0000000..11657d5 --- /dev/null +++ b/geotribu_cli/json/json_client.py @@ -0,0 +1,58 @@ +from typing import Any + +import requests +from requests import Response + +from geotribu_cli.__about__ import __executable_name__, __version__ + +JSON_FEED_URL = "https://geotribu.fr/feed_json_created.json" +JSON_TAGS_URL = "https://geotribu.fr/tags.json" + +HEADERS: dict = { + b"Accept": b"application/json", + b"User-Agent": bytes(f"{__executable_name__}/{__version__}", "utf8"), +} + + +class JsonFeedClient: + def __init__(self, url: str = JSON_FEED_URL, tags_url: str = JSON_TAGS_URL): + """ + Class initialization + + Args: + url: JSON feed URL, defaults to https://geotribu.fr/feed_json_created.json + tags_url: JSON tags URL, defaults to https://geotribu.fr/tags.json + """ + self.url = url + self.tags_url = tags_url + + @property + def items(self) -> list[dict[str, Any]]: + """ + Fetch Geotribu JSON feed items + + Returns: + List of dicts representing raw JSON feed items + """ + r: Response = requests.get(self.url, headers=HEADERS) + r.raise_for_status() + return r.json()["items"] + + @property + def tags(self, should_sort: bool = False) -> list[str]: + """ + Fetch Geotribu used tags + + Args: + should_sort: if the list of returned tags should be alphabetically sorted + + Returns: + List of tags used by Geotribu + """ + r: Response = requests.get(self.tags_url, headers=HEADERS) + r.raise_for_status() + tags = set() + for item in r.json()["mappings"]: + for tag in item["tags"]: + tags.add(tag) + return sorted(tags) if should_sort else list(tags) From 93ca7e89b078b36cc3d70733828040ee9ee3d220 Mon Sep 17 00:00:00 2001 From: gounux Date: Fri, 26 Apr 2024 09:45:54 +0200 Subject: [PATCH 2/5] Remove property for JSON items and tags --- geotribu_cli/json/json_client.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/geotribu_cli/json/json_client.py b/geotribu_cli/json/json_client.py index 11657d5..14e26f8 100644 --- a/geotribu_cli/json/json_client.py +++ b/geotribu_cli/json/json_client.py @@ -26,7 +26,6 @@ def __init__(self, url: str = JSON_FEED_URL, tags_url: str = JSON_TAGS_URL): self.url = url self.tags_url = tags_url - @property def items(self) -> list[dict[str, Any]]: """ Fetch Geotribu JSON feed items @@ -38,7 +37,6 @@ def items(self) -> list[dict[str, Any]]: r.raise_for_status() return r.json()["items"] - @property def tags(self, should_sort: bool = False) -> list[str]: """ Fetch Geotribu used tags From 4a85ebc1a8ff7da06787daf7bd722aa83741faf3 Mon Sep 17 00:00:00 2001 From: gounux Date: Fri, 26 Apr 2024 09:48:31 +0200 Subject: [PATCH 3/5] Add tests for JSON client --- tests/test_json_client.py | 46 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 tests/test_json_client.py diff --git a/tests/test_json_client.py b/tests/test_json_client.py new file mode 100644 index 0000000..50a896d --- /dev/null +++ b/tests/test_json_client.py @@ -0,0 +1,46 @@ +import unittest + +from geotribu_cli.json.json_client import JsonFeedClient + + +class TestJsonClient(unittest.TestCase): + """Test Geotribu JSON client.""" + + def __init__(self, methodName: str = "runTest") -> None: + super().__init__(methodName) + self.client = JsonFeedClient() + self.items = self.client.items() + self.tags = self.client.tags() + + def test_items_exist(self): + self.assertGreater(len(self.items), 0) + + def test_some_existing_items(self): + titles = [i["title"] for i in self.items] + self.assertIn( + "Automatisation de publication des données de qualité de l'air sur Mastodon", + titles, + ) + self.assertIn("Le crowdsourcing avec cocarto", titles) + self.assertIn( + "De Twitter (X) à Mastodon : guide pour les géomaticien/nes", titles + ) + + def test_tags_exist(self): + self.assertGreater(len(self.tags), 0) + + def test_some_existing_tags(self): + for tag in ["OpenLayers", "QGIS", "OpenStreetMap", "QFieldCloud"]: + self.assertIn(tag, self.tags) + + def test_unexisting_tags(self): + for tag in ["Kinkeliba", "Jogging", "cziygiyezrvcyryez"]: + self.assertNotIn(tag, self.tags) + + def test_sorted_tags(self): + sorted_tags = self.client.tags(should_sort=True) + i = 1 + while i < len(sorted_tags): + if sorted_tags[i] < sorted_tags[i - 1]: + raise Exception("Tags are not alphabetically sorted") + i += 1 From d6200beff8a33cefeab311ec7c2c829f1182a74d Mon Sep 17 00:00:00 2001 From: gounux Date: Fri, 26 Apr 2024 09:53:14 +0200 Subject: [PATCH 4/5] Add JSON feed length test --- tests/test_json_client.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_json_client.py b/tests/test_json_client.py index 50a896d..f4b3041 100644 --- a/tests/test_json_client.py +++ b/tests/test_json_client.py @@ -14,6 +14,7 @@ def __init__(self, methodName: str = "runTest") -> None: def test_items_exist(self): self.assertGreater(len(self.items), 0) + self.assertEqual(len(self.items), 50) def test_some_existing_items(self): titles = [i["title"] for i in self.items] From 84c62598ce159f1267284a2acf67e93690e1385d Mon Sep 17 00:00:00 2001 From: gounux Date: Fri, 26 Apr 2024 12:47:56 +0200 Subject: [PATCH 5/5] Remove items test --- tests/test_json_client.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/tests/test_json_client.py b/tests/test_json_client.py index f4b3041..6694354 100644 --- a/tests/test_json_client.py +++ b/tests/test_json_client.py @@ -16,17 +16,6 @@ def test_items_exist(self): self.assertGreater(len(self.items), 0) self.assertEqual(len(self.items), 50) - def test_some_existing_items(self): - titles = [i["title"] for i in self.items] - self.assertIn( - "Automatisation de publication des données de qualité de l'air sur Mastodon", - titles, - ) - self.assertIn("Le crowdsourcing avec cocarto", titles) - self.assertIn( - "De Twitter (X) à Mastodon : guide pour les géomaticien/nes", titles - ) - def test_tags_exist(self): self.assertGreater(len(self.tags), 0)