diff --git a/app/knowledge_panels.py b/app/knowledge_panels.py index 0f8970d..ffca962 100644 --- a/app/knowledge_panels.py +++ b/app/knowledge_panels.py @@ -1,167 +1,232 @@ +import logging from typing import Union from urllib.parse import urlencode -from .models import HungerGameFilter, country_to_ISO_code, facet_plural +from .models import country_to_ISO_code, facet_plural from .off import data_quality, hungergame, last_edit, wikidata_helper -def hunger_game_kp( - hunger_game_filter: HungerGameFilter, - value: Union[str, None] = None, - country: Union[str, None] = None, -): - query = {} - description = "" - if hunger_game_filter == "country": - country = value - hunger_game_filter = value = None - if country is not None: - query["country"] = country - description = country - if hunger_game_filter is not None: - query["type"] = f"{hunger_game_filter}" - description = f"{hunger_game_filter}" - if value is not None: - query["value_tag"] = value - description = f"{value} {hunger_game_filter}" - questions_url = "https://hunger.openfoodfacts.org/questions" - if query: - questions_url += f"?{urlencode(query)}" - t_description = hungergame() - description = f"{t_description} {description}" - html = f"

{description}

\n" - return { - "hunger-game": { - "elements": [ +class KnowledgePanels: + def __init__( + self, + facet: str, + value: Union[str, None] = None, + sec_facet: Union[str, None] = None, + sec_value: Union[str, None] = None, + country: Union[str, None] = None, + ): + self.facet = facet + self.value = value + self.sec_facet = sec_facet + self.sec_value = sec_value + self.country = country + + def hunger_game_kp(self): + query = {} + questions_url = "https://hunger.openfoodfacts.org/questions" + facets = {self.facet: self.value, self.sec_facet: self.sec_value} + filtered = {k: v for k, v in facets.items() if k is not None} + facets.clear() + facets.update(filtered) + urls = set() + description = "" + html = [] + if self.country is not None: + query["country"] = f"en:{self.country}" + description = f"for country {self.country}" + if facets.get("country"): + country_value = facets.pop("country") + query["country"] = f"en:{country_value}" + description = f"{country_value}" + if facets.get("brand") and len(facets) > 1: + brand_value = facets.pop("brand") + query["brand"] = brand_value + description += f" for brand {brand_value}" + # generate an url for each remaining facets + for k, v in facets.items(): + value_description = "" + facet_query = dict(query) + facet_query["type"] = k + facet_description = k + if v is not None: + facet_query["value_tag"] = v + value_description += v + urls.add( + ( + f"{questions_url}?{urlencode(facet_query)}", + f"{facet_description} {value_description} {description}".strip(), + ) + ) + if query: + urls.add((f"{questions_url}?{urlencode(query)}", description)) + + t_description = hungergame() + for id, val in enumerate(sorted(urls)): + url, des = val + html.append( { + "id": id, "element_type": "text", - "text_element": {"html": str(html)}, + "text_element": {"html": f"

{t_description} {des}

"}, }, - ], - }, - } - - -def data_quality_kp( - facet, - value: Union[str, None] = None, - country: Union[str, None] = None, -): - """ - Get data corresponding to differnet facet - """ - path = "" - description = "" - if facet == "country": - country = value - country_code = country_to_ISO_code(value=value) - url = f"https://{country_code}-en.openfoodfacts.org" - path = "" - facet = value = None - if country is not None: - country_code = country_to_ISO_code(value=country) - url = f"https://{country_code}-en.openfoodfacts.org" + ) + + kp = {"hunger-game": {"title": "hunger-games", "elements": html}} + + return kp + + def data_quality_kp(self): + """ + Get data corresponding to differnet facet + """ path = "" - description += f"{country} " - if country is None: - url = "https://world.openfoodfacts.org/" - if facet is not None: - path += facet - description += f"{facet}" - if value is not None: - path += f"/{value}" - description += f" {value}" - (quality_html, source_url, t_description, t_title) = data_quality(url=url, path=path) - - return { - "Quality": { - "title": t_title, - "subtitle": f"{t_description} {description}", - "source_url": f"{source_url}/data-quality", - "elements": [ + description = "" + if self.facet == "country": + self.country = self.value + country_code = country_to_ISO_code(value=self.value) + url = f"https://{country_code}.openfoodfacts.org" + path = "" + self.facet = self.value = None + if self.sec_facet == "country": + self.country = self.sec_value + country_code = country_to_ISO_code(value=self.sec_value) + url = f"https://{country_code}.openfoodfacts.org" + path = "" + self.sec_facet = self.sec_value = None + if self.country is not None: + country_code = country_to_ISO_code(value=self.country) + url = f"https://{country_code}.openfoodfacts.org" + path = "" + description += f"{self.country} " + if self.country is None: + url = "https://world.openfoodfacts.org/" + if self.facet is not None: + path += self.facet + description += f"{self.facet}" + if self.value is not None: + path += f"/{self.value}" + description += f" {self.value}" + # Checking if secondary facet is provided + if self.sec_facet is not None: + path += f"/{self.sec_facet}" + description += f" {self.sec_facet}" + if self.sec_value is not None: + path += f"/{self.sec_value}" + description += f" {self.sec_value}" + (t_html, source_url, t_description, t_title) = data_quality(url=url, path=path) + + return { + "Quality": { + "title": t_title, + "subtitle": f"{t_description} {description}", + "source_url": f"{source_url}/data-quality", + "elements": [ + { + "element_type": "text", + "text_element": t_html, + } + ], + }, + } + + def last_edits_kp(self): + """ + Return knowledge panel for last-edits corresponding to different facet + """ + query = { + "fields": "product_name,code,last_editor,last_edit_dates_tags", + "sort_by": "last_modified_t", + } + description = "" + if self.facet == "country": + self.country = self.value + country_code = country_to_ISO_code(value=self.value) + url = f"https://{country_code}.openfoodfacts.org" + self.facet = self.value = None + if self.sec_facet == "country": + self.country = self.sec_value + country_code = country_to_ISO_code(value=self.sec_value) + url = f"https://{country_code}.openfoodfacts.org" + self.sec_facet = self.sec_value = None + if self.country is not None: + country_code = country_to_ISO_code(value=self.country) + url = f"https://{country_code}.openfoodfacts.org" + description += f"{self.country} " + if self.country is None: + url = "https://world.openfoodfacts.org" + if self.facet is not None: + description += f"{self.facet}" + if self.value is not None: + query[f"{facet_plural(facet=self.facet)}_tags_en"] = self.value + description += f" {self.value}" + source_url = f"{url}/{self.facet}/{self.value}?sort_by=last_modified_t" + if self.sec_value and self.sec_facet is not None: + query[f"{facet_plural(facet=self.sec_facet)}_tags_en"] = self.sec_value + description += f" {self.sec_facet} {self.sec_value}" + source_url = f"{url}/{self.facet}/{self.value}/{self.sec_facet}/{self.sec_value}?sort_by=last_modified_t" # noqa: E501 + t_html, t_description, t_title = last_edit(url=url, query=query) + + return { + "LastEdits": { + "title": t_title, + "subtitle": f"{t_description} {description}", + "source_url": source_url, + "elements": [ + { + "element_type": "text", + "text_element": t_html, + }, + ], + }, + } + + def _wikidata_kp(self, facet, value): + query = {} + if value: + query["tagtype"] = facet_plural(facet=facet) + query["fields"] = "wikidata" + query["tags"] = value + + entities = wikidata_helper(query=query, value=value) + + return entities + + def wikidata_kp(self): + """ + Return knowledge panel for wikidata + """ + entities = set() + try: + entities.add(self._wikidata_kp(facet=self.facet, value=self.value)) + except Exception: + logging.exception("While adding wikidata for primary facet") + try: + entities.add(self._wikidata_kp(facet=self.sec_facet, value=self.sec_value)) + except Exception: + logging.exception("While adding wikidata for secandary facet") + + html = [] + for id, val in enumerate(entities): + html.append( { - "element_type": "text", - "text_element": quality_html, + "id": id, + "subtitle": val.description_tag, + "source_url": f"https://www.wikidata.org/wiki/{val.entity_id}", + "elements": [ + { + "element_type": "text", + "text_element": val.label_tag, + }, + { + "element_type": "links", + "wikipedia": val.wikipedia_relation, + "image_url": val.image_url, + "open_street_map": val.OSM_relation, + "INAO": val.INAO_relation, + }, + ], } - ], - }, - } - - -def last_edits_kp( - facet: str, - value: Union[str, None] = None, - country: Union[str, None] = None, -): - """ - Return knowledge panel for last-edits corresponding to different facet - """ - query = { - "fields": "product_name,code,last_editor,last_edit_dates_tags", - "sort_by": "last_modified_t", - } - description = "" - if facet == "country": - country = value - country_code = country_to_ISO_code(value=value) - url = f"https://{country_code}-en.openfoodfacts.org" - facet = value = None - if country is not None: - country_code = country_to_ISO_code(value=country) - url = f"https://{country_code}-en.openfoodfacts.org" - description += f"{country} " - if country is None: - url = "https://world.openfoodfacts.org" - if facet is not None: - description += f"{facet}" - if value is not None: - query[f"{facet_plural(facet=facet)}_tags_en"] = value - description += f" {value}" - expected_html, t_description, t_title = last_edit(url=url, query=query) - - return { - "LastEdits": { - "title": t_title, - "subtitle": f"{t_description} {description}", - "source_url": f"{url}/{facet}/{value}?sort_by=last_modified_t", - "elements": [ - { - "element_type": "text", - "text_element": expected_html, - }, - ], - }, - } - - -def wikidata_kp(facet: str, value: str): - """ - Return knowledge panel for wikidata - """ - query = {} - if value: - query["tagtype"] = facet_plural(facet=facet) - query["fields"] = "wikidata" - query["tags"] = value - - entities = wikidata_helper(query=query, value=value) - return { - "WikiData": { - "title": "wiki-data", - "subtitle": entities.description_tag, - "source_url": f"https://www.wikidata.org/wiki/{entities.entity_id}", - "elements": [ - { - "element_type": "text", - "text_element": entities.label_tag, - "image_url": entities.image_url, - }, - { - "element_type": "links", - "wikipedia": entities.wikipedia_relation, - "open_street_map": entities.OSM_relation, - "INAO": entities.INAO_relation, - }, - ], - }, - } + ) + return { + "WikiData": {"title": "wiki-data", "elements": html}, + } diff --git a/app/main.py b/app/main.py index e88cd5d..7b25ead 100644 --- a/app/main.py +++ b/app/main.py @@ -4,8 +4,8 @@ from fastapi import FastAPI from .i18n import active_translation -from .knowledge_panels import data_quality_kp, hunger_game_kp, last_edits_kp, wikidata_kp -from .models import FacetName, HungerGameFilter, Taxonomies +from .knowledge_panels import KnowledgePanels +from .models import FacetName, HungerGameFilter app = FastAPI() @@ -19,6 +19,8 @@ def hello(): def knowledge_panel( facet_tag: FacetName, value_tag: Union[str, None] = None, + sec_facet_tag: Union[str, None] = None, + sec_value_tag: Union[str, None] = None, lang_code: Union[str, None] = None, country: Union[str, None] = None, ): @@ -29,22 +31,29 @@ def knowledge_panel( """ with active_translation(lang_code): panels = [] - if facet_tag in HungerGameFilter.list(): - panels.append( - hunger_game_kp(hunger_game_filter=facet_tag, value=value_tag, country=country) - ) + obj_kp = KnowledgePanels( + facet=facet_tag.value, + value=value_tag, + sec_facet=sec_facet_tag, + sec_value=sec_value_tag, + country=country, + ) try: - panels.append(data_quality_kp(facet=facet_tag, value=value_tag, country=country)) + if facet_tag in HungerGameFilter.list(): + panels.append(obj_kp.hunger_game_kp()) + except Exception: + logging.exception("error occued while appending hungergames-kp") + try: + panels.append(obj_kp.data_quality_kp()) except Exception: logging.exception("error occued while appending data-quality-kp") try: - panels.append(last_edits_kp(facet=facet_tag, value=value_tag, country=country)) + panels.append(obj_kp.last_edits_kp()) except Exception: - logging.exception("error occued while appending last-edits-kp") + logging.exception("error occued while appending last-edites-kp") try: - if facet_tag in Taxonomies.list(): - panels.append(wikidata_kp(facet=facet_tag, value=value_tag)) + panels.append(obj_kp.wikidata_kp()) except Exception: - logging.exception("error occurred while appending wikidata-kp") + logging.exception("error occued while appending wikidata-kp") return {"knowledge_panels": panels} diff --git a/app/models.py b/app/models.py index 15b5002..a7f04b5 100644 --- a/app/models.py +++ b/app/models.py @@ -79,8 +79,10 @@ def country_to_ISO_code(value: str): Helper function that return ISO code for country """ country_data = pycountry.countries.get(name=value) - country_iso_code = country_data.alpha_2 - return country_iso_code.lower() + if country_data is not None: + country_iso_code = country_data.alpha_2 + return f"{country_iso_code.lower()}-en" + return "world" def facet_plural(facet: str): diff --git a/tests/test_knowledge_panels.py b/tests/test_knowledge_panels.py index 9804e90..2af1d31 100644 --- a/tests/test_knowledge_panels.py +++ b/tests/test_knowledge_panels.py @@ -2,9 +2,8 @@ import requests import wikidata.client -import app.main from app.i18n import active_translation -from app.main import hunger_game_kp +from app.knowledge_panels import KnowledgePanels from app.wikidata_utils import wikidata_props from .test_utils import DictAttr, mock_get_factory, mock_wikidata_get, tidy_html @@ -19,19 +18,19 @@ def auto_activate_lang(): def test_hunger_game_kp_with_filter_value_and_country(): html = ( - "

" - "Answer robotoff questions about germany

\n" + "

" + "Answer robotoff questions about germany

" ) - assert hunger_game_kp(hunger_game_filter="country", value="germany", country="france") == { + assert KnowledgePanels(facet="country", value="germany", country="france").hunger_game_kp() == { "hunger-game": { + "title": "hunger-games", "elements": [ { + "id": 0, "element_type": "text", - "text_element": { - "html": html, - }, + "text_element": {"html": html}, } - ] + ], } } @@ -39,56 +38,57 @@ def test_hunger_game_kp_with_filter_value_and_country(): def test_hunger_game_kp_with_category(): html = ( "

" - "Answer robotoff questions about category

\n" + "Answer robotoff questions about category

" ) - assert hunger_game_kp(hunger_game_filter="category") == { + assert KnowledgePanels(facet="category").hunger_game_kp() == { "hunger-game": { + "title": "hunger-games", "elements": [ { + "id": 0, "element_type": "text", - "text_element": { - "html": html, - }, + "text_element": {"html": html}, } - ] + ], } } def test_hunger_game_kp_category_with_country(): - html = ( - "

" - "Answer robotoff questions about category

\n" + html0 = ( + "

" + "Answer robotoff questions about for country france

" + ) + html1 = ( + "

" + "Answer robotoff questions about category for country france

" ) - assert hunger_game_kp(hunger_game_filter="category", country="france") == { + assert KnowledgePanels(facet="category", country="france").hunger_game_kp() == { "hunger-game": { + "title": "hunger-games", "elements": [ - { - "element_type": "text", - "text_element": { - "html": html, - }, - } - ] + {"id": 0, "element_type": "text", "text_element": {"html": html0}}, + {"id": 1, "element_type": "text", "text_element": {"html": html1}}, + ], } } def test_hunger_game_kp_category_with_value(): html = ( - "

" - "Answer robotoff questions about beer category

\n" + "

" # noqa: E501 + "Answer robotoff questions about category en:beers

" ) - assert hunger_game_kp(hunger_game_filter="category", value="beer") == { + assert KnowledgePanels(facet="category", value="en:beers").hunger_game_kp() == { "hunger-game": { + "title": "hunger-games", "elements": [ { + "id": 0, "element_type": "text", - "text_element": { - "html": html, - }, + "text_element": {"html": html}, } - ] + ], } } @@ -96,37 +96,113 @@ def test_hunger_game_kp_category_with_value(): def test_hunger_game_kp_brand_with_value(): html = ( "

" - "Answer robotoff questions about nestle brand

\n" + "Answer robotoff questions about brand nestle

" ) - assert hunger_game_kp(hunger_game_filter="brand", value="nestle") == { + assert KnowledgePanels(facet="brand", value="nestle").hunger_game_kp() == { "hunger-game": { - "elements": [ - { - "element_type": "text", - "text_element": { - "html": html, - }, - } - ] + "title": "hunger-games", + "elements": [{"id": 0, "element_type": "text", "text_element": {"html": html}}], } } def test_hunger_game_kp_label_with_value(): html = ( - "

" - "Answer robotoff questions about organic label

\n" + "

" + "Answer robotoff questions about label en:organic

" ) - assert hunger_game_kp(hunger_game_filter="label", value="organic") == { + assert KnowledgePanels(facet="label", value="en:organic").hunger_game_kp() == { "hunger-game": { + "title": "hunger-games", "elements": [ { + "id": 0, "element_type": "text", - "text_element": { - "html": html, - }, + "text_element": {"html": html}, } - ] + ], + } + } + + +def test_hunger_game_kp_with_all_tag_1(): + html0 = ( + "

" + "Answer robotoff questions about for country france for brand lidl

" + ) + html1 = ( + "

" # noqa: E501 + "Answer robotoff questions about category en:beers for country france for brand lidl

" # noqa: E501 + ) + assert KnowledgePanels( + facet="category", + value="en:beers", + sec_facet="brand", + sec_value="lidl", + country="france", + ).hunger_game_kp() == { + "hunger-game": { + "title": "hunger-games", + "elements": [ + {"id": 0, "element_type": "text", "text_element": {"html": html0}}, + {"id": 1, "element_type": "text", "text_element": {"html": html1}}, + ], + } + } + + +def test_hunger_game_kp_with_all_tag_2(): + + html0 = ( + "

" + "Answer robotoff questions about brand

" + ) + html1 = ( + "

" # noqa: E501 + "Answer robotoff questions about category en:coffees

" + ) + assert KnowledgePanels( + facet="brand", + sec_facet="category", + sec_value="en:coffees", + ).hunger_game_kp() == { + "hunger-game": { + "title": "hunger-games", + "elements": [ + {"id": 0, "element_type": "text", "text_element": {"html": html0}}, + {"id": 1, "element_type": "text", "text_element": {"html": html1}}, + ], + } + } + + +def test_hunger_game_kp_with_all_tag_3(): + html0 = ( + "

" + "Answer robotoff questions about for country italy

" + ) + html1 = ( + "

" # noqa: E501 + "Answer robotoff questions about category en:meals for country italy

" + ) + html2 = ( + "

" # noqa: E501 + "Answer robotoff questions about label vegan for country italy

" + ) + assert KnowledgePanels( + facet="category", + value="en:meals", + sec_facet="label", + sec_value="vegan", + country="italy", + ).hunger_game_kp() == { + "hunger-game": { + "title": "hunger-games", + "elements": [ + {"id": 0, "element_type": "text", "text_element": {"html": html0}}, + {"id": 1, "element_type": "text", "text_element": {"html": html1}}, + {"id": 2, "element_type": "text", "text_element": {"html": html2}}, + ], } } @@ -164,7 +240,7 @@ def test_data_quality_kp_with_country(monkeypatch): } monkeypatch.setattr(requests, "get", mock_get_factory(expected_url, json_content=json_content)) - result = app.main.data_quality_kp(facet="country", value="Turkey", country="Hungary") + result = KnowledgePanels(facet="country", value="Turkey", country="Hungary").data_quality_kp() first_element = result["Quality"]["elements"][0] first_element["text_element"] = tidy_html(first_element["text_element"]) expected_text = """ @@ -200,7 +276,7 @@ def test_data_quality_kp_with_country(monkeypatch): } -def test_data_quality_kp_with_all_three_values(monkeypatch): +def test_data_quality_kp_with_one_facet_and_value(monkeypatch): expected_url = "https://world.openfoodfacts.org/brand/lidl/data-quality.json" base_url = "https://world.openfoodfacts.org/brand/lidl/data-quality" json_content = { @@ -233,7 +309,7 @@ def test_data_quality_kp_with_all_three_values(monkeypatch): } monkeypatch.setattr(requests, "get", mock_get_factory(expected_url, json_content=json_content)) - result = app.main.data_quality_kp(facet="brand", value="lidl") + result = KnowledgePanels(facet="brand", value="lidl").data_quality_kp() first_element = result["Quality"]["elements"][0] first_element["text_element"] = tidy_html(first_element["text_element"]) expected_text = """ @@ -269,7 +345,77 @@ def test_data_quality_kp_with_all_three_values(monkeypatch): } -def test_last_edits_kp_with_all_three_values(monkeypatch): +def test_data_quality_kp_with_all_tags(monkeypatch): + expected_url = ( + "https://world.openfoodfacts.org/category/beers/brand/budweiser/data-quality.json" + ) + json_content = { + "count": 24, + "tags": [ + { + "id": "en:alcoholic-beverages-category-without-alcohol-value", + "known": 0, + "name": "alcoholic-beverages-category-without-alcohol-value", + "products": 13, + "url": "https://world.openfoodfacts.org/category/beers/data-quality/alcoholic-beverages-category-without-alcohol-value", # noqa: E501 # allow long lines + }, + { + "id": "en:ecoscore-production-system-no-label", + "known": 0, + "name": "ecoscore-production-system-no-label", + "products": 13, + "url": "https://world.openfoodfacts.org/category/beers/data-quality/ecoscore-production-system-no-label", # noqa: E501 # allow long lines + }, + { + "id": "en:ecoscore-origins-of-ingredients-origins-are-100-percent-unknown", + "known": 0, + "name": "ecoscore-origins-of-ingredients-origins-are-100-percent-unknown", + "products": 12, + "url": "https://world.openfoodfacts.org/category/beers/data-quality/ecoscore-origins-of-ingredients-origins-are-100-percent-unknown", # noqa: E501 # allow long lines + }, + ], + } + + monkeypatch.setattr(requests, "get", mock_get_factory(expected_url, json_content=json_content)) + result = KnowledgePanels( + facet="category", value="beers", sec_facet="brand", sec_value="budweiser" + ).data_quality_kp() + first_element = result["Quality"]["elements"][0] + first_element["text_element"] = tidy_html(first_element["text_element"]) + expected_text = """ + + """ # noqa: E501 # allow long lines + # assert html separately to have better output in case of error + assert first_element["text_element"] == tidy_html(expected_text) + # now replace it for concision of output + first_element["text_element"] = "ok" + assert result == { + "Quality": { + "title": "Data-quality issues", + "subtitle": "Data-quality issues related to category beers brand budweiser", + "source_url": "https://world.openfoodfacts.org/category/beers/brand/budweiser/data-quality", # noqa: E501 # allow long lines + "elements": [ + { + "element_type": "text", + "text_element": "ok", + } + ], + } + } + + +def test_last_edits_kp_with_one_facet_and_value(monkeypatch): expected_url = "https://hu-en.openfoodfacts.org/api/v2/search" expected_kwargs = { "params": { @@ -301,7 +447,7 @@ def test_last_edits_kp_with_all_three_values(monkeypatch): json_content, ), ) - result = app.main.last_edits_kp(facet="vitamin", value="vitamin-k", country="hungary") + result = KnowledgePanels(facet="vitamin", value="vitamin-k", country="hungary").last_edits_kp() first_element = result["LastEdits"]["elements"][0] first_element["text_element"] = tidy_html(first_element["text_element"]) last_edits_text = """ @@ -333,6 +479,150 @@ def test_last_edits_kp_with_all_three_values(monkeypatch): } +def test_last_edits_kp_with_all_tags(monkeypatch): + expected_url = "https://fr-en.openfoodfacts.org/api/v2/search" + expected_kwargs = { + "params": { + "fields": "product_name,code,last_editor,last_edit_dates_tags", + "sort_by": "last_modified_t", + "brands_tags_en": "nestle", + "categories_tags_en": "coffees", + } + } + json_content = { + "count": 112, + "page": 1, + "page_count": 24, + "page_size": 24, + "products": [ + { + "code": "7613036271868", + "last_edit_dates_tags": ["2022-08-31", "2022-08", "2022"], + "last_editor": "org-nestle-france", + "product_name": "Capsules NESCAFE Dolce Gusto Cappuccino Extra Crema 16 Capsules", + }, + { + "code": "7613032655495", + "last_edit_dates_tags": ["2022-08-30", "2022-08", "2022"], + "last_editor": "feat", + "product_name": "RICORE Original, Café & Chicorée, Boîte 260g", + }, + { + "code": "7613036303521", + "last_edit_dates_tags": ["2022-08-28", "2022-08", "2022"], + "last_editor": "feat", + "product_name": "Ricoré", + }, + { + "code": "3033710072927", + "last_edit_dates_tags": ["2022-08-28", "2022-08", "2022"], + "last_editor": "org-nestle-france", + "product_name": "NESCAFÉ NES, Café Soluble, Boîte de 25 Sticks (2g chacun)", + }, + { + "code": "3033710076017", + "last_edit_dates_tags": ["2022-08-28", "2022-08", "2022"], + "last_editor": "org-nestle-france", + "product_name": "NESCAFÉ SPECIAL FILTRE L'Original, Café Soluble, Boîte de 25 Sticks", # noqa: E501 # allow long lines + }, + { + "code": "3033710074624", + "last_edit_dates_tags": ["2022-08-28", "2022-08", "2022"], + "last_editor": "org-nestle-france", + "product_name": "NESCAFÉ SPECIAL FILTRE Décaféiné, Café Soluble, Flacon de 200g", + }, + { + "code": "7613034056122", + "last_edit_dates_tags": ["2022-08-28", "2022-08", "2022"], + "last_editor": "org-nestle-france", + "product_name": "NESCAFÉ SPECIAL FILTRE L'Original, Café Soluble, Recharge de 150g", + }, + { + "code": "3033710074525", + "last_edit_dates_tags": ["2022-08-28", "2022-08", "2022"], + "last_editor": "org-nestle-france", + "product_name": "NESCAFÉ SPECIAL FILTRE L'Original Flacon de 200g", + }, + { + "code": "3033710074518", + "last_edit_dates_tags": ["2022-08-28", "2022-08", "2022"], + "last_editor": "org-nestle-france", + }, + { + "code": "7891000300602", + "last_edit_dates_tags": ["2022-08-27", "2022-08", "2022"], + "last_editor": "5m4u9", + "product_name": "Original", + }, + ], + } + monkeypatch.setattr( + requests, + "get", + mock_get_factory( + expected_url, + expected_kwargs, + json_content, + ), + ) + result = KnowledgePanels( + facet="brand", + value="nestle", + sec_facet="category", + sec_value="coffees", + country="france", + ).last_edits_kp() + first_element = result["LastEdits"]["elements"][0] + first_element["text_element"] = tidy_html(first_element["text_element"]) + last_edits_text = """ + + """ # noqa: E501 # allow long lines + # assert html separately to have better output in case of error + assert first_element["text_element"] == tidy_html(last_edits_text) + # now replace it for concision of output + first_element["text_element"] = "ok" + assert result == { + "LastEdits": { + "title": "Last-edits", + "subtitle": "last-edits issues related to france brand nestle category coffees", + "source_url": "https://fr-en.openfoodfacts.org/brand/nestle/category/coffees?sort_by=last_modified_t", # noqa: E501 # allow long lines + "elements": [{"element_type": "text", "text_element": "ok"}], + } + } + + def test_wikidata_kp(monkeypatch): # first mock the call to open food facts (to get the wikidata property) expected_url = "https://world.openfoodfacts.org/api/v2/taxonomy" @@ -378,53 +668,58 @@ def test_wikidata_kp(monkeypatch): mock_wikidata_get("Q470974", fake_entity), ) # run the test - result = app.main.wikidata_kp(facet="category", value="fr:fitou") + result = KnowledgePanels(facet="category", value="fr:fitou").wikidata_kp() expected_result = { "WikiData": { "title": "wiki-data", - "subtitle": "French wine appellation", - "source_url": "https://www.wikidata.org/wiki/Q470974", "elements": [ { - "element_type": "text", - "text_element": "Fitou AOC", - "image_url": image_url, - }, - { - "element_type": "links", - "wikipedia": "http://en.wikipedia.org/wiki/Fitou_AOC", - "open_street_map": "https://www.openstreetmap.org/relation/2727716", - "INAO": "https://www.inao.gouv.fr/produit/6159", + "id": 0, + "subtitle": "French wine appellation", + "source_url": "https://www.wikidata.org/wiki/Q470974", + "elements": [ + {"element_type": "text", "text_element": "Fitou AOC"}, + { + "element_type": "links", + "wikipedia": "http://en.wikipedia.org/wiki/Fitou_AOC", + "image_url": image_url, + "open_street_map": "https://www.openstreetmap.org/relation/2727716", + "INAO": "https://www.inao.gouv.fr/produit/6159", + }, + ], }, ], } } + assert result == expected_result with active_translation("it"): # fallbacks to english - result_it = app.main.wikidata_kp(facet="category", value="fr:fitou") + result_it = KnowledgePanels(facet="category", value="fr:fitou").wikidata_kp() assert result_it == expected_result with active_translation("fr"): # only some items varies expected_result_fr = { "WikiData": { "title": "wiki-data", - "subtitle": "région viticole", - "source_url": "https://www.wikidata.org/wiki/Q470974", "elements": [ { - "element_type": "text", - "text_element": "Fitou", - "image_url": image_url, - }, - { - "element_type": "links", - "wikipedia": "http://fr.wikipedia.org/wiki/Fitou_AOC", - "open_street_map": "https://www.openstreetmap.org/relation/2727716", - "INAO": "https://www.inao.gouv.fr/produit/6159", + "id": 0, + "subtitle": "région viticole", + "source_url": "https://www.wikidata.org/wiki/Q470974", + "elements": [ + {"element_type": "text", "text_element": "Fitou"}, + { + "element_type": "links", + "wikipedia": "http://fr.wikipedia.org/wiki/Fitou_AOC", + "image_url": image_url, + "open_street_map": "https://www.openstreetmap.org/relation/2727716", + "INAO": "https://www.inao.gouv.fr/produit/6159", + }, + ], }, ], } } - result_fr = app.main.wikidata_kp(facet="category", value="fr:fitou") + result_fr = KnowledgePanels(facet="category", value="fr:fitou").wikidata_kp() assert result_fr == expected_result_fr