Skip to content

Commit e5474de

Browse files
authored
feat(Taxonomy): allow fetching taxonomies from other flavors (obf, opff, opf) (#466)
1 parent af1f622 commit e5474de

1 file changed

Lines changed: 82 additions & 50 deletions

File tree

src/openfoodfacts/taxonomy.py

Lines changed: 82 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -21,52 +21,79 @@
2121
DEFAULT_CACHE_DIR = Path("~/.cache/openfoodfacts/taxonomy").expanduser()
2222

2323

24-
# Only available for Open Food Facts for now (not other flavors)
2524
TAXONOMY_URLS = {
26-
TaxonomyType.category: URLBuilder.static(Flavor.off, Environment.org)
27-
+ "/data/taxonomies/categories.full.json",
28-
TaxonomyType.ingredient: URLBuilder.static(Flavor.off, Environment.org)
29-
+ "/data/taxonomies/ingredients.full.json",
30-
TaxonomyType.label: URLBuilder.static(Flavor.off, Environment.org)
31-
+ "/data/taxonomies/labels.full.json",
32-
TaxonomyType.brand: URLBuilder.static(Flavor.off, Environment.org)
33-
+ "/data/taxonomies/brands.full.json",
34-
TaxonomyType.packaging_shape: URLBuilder.static(Flavor.off, Environment.org)
35-
+ "/data/taxonomies/packaging_shapes.full.json",
36-
TaxonomyType.packaging_material: URLBuilder.static(Flavor.off, Environment.org)
37-
+ "/data/taxonomies/packaging_materials.full.json",
38-
TaxonomyType.packaging_recycling: URLBuilder.static(Flavor.off, Environment.org)
39-
+ "/data/taxonomies/packaging_recycling.full.json",
40-
TaxonomyType.country: URLBuilder.static(Flavor.off, Environment.org)
41-
+ "/data/taxonomies/countries.full.json",
42-
TaxonomyType.store: URLBuilder.static(Flavor.off, Environment.org)
43-
+ "/data/taxonomies/stores.full.json",
44-
TaxonomyType.nova_group: URLBuilder.static(Flavor.off, Environment.org)
45-
+ "/data/taxonomies/nova_groups.full.json",
46-
TaxonomyType.additive: URLBuilder.static(Flavor.off, Environment.org)
47-
+ "/data/taxonomies/additives.full.json",
48-
TaxonomyType.vitamin: URLBuilder.static(Flavor.off, Environment.org)
49-
+ "/data/taxonomies/vitamins.full.json",
50-
TaxonomyType.mineral: URLBuilder.static(Flavor.off, Environment.org)
51-
+ "/data/taxonomies/minerals.full.json",
52-
TaxonomyType.amino_acid: URLBuilder.static(Flavor.off, Environment.org)
53-
+ "/data/taxonomies/amino_acids.full.json",
54-
TaxonomyType.nucleotide: URLBuilder.static(Flavor.off, Environment.org)
55-
+ "/data/taxonomies/nucleotides.full.json",
56-
TaxonomyType.allergen: URLBuilder.static(Flavor.off, Environment.org)
57-
+ "/data/taxonomies/allergens.full.json",
58-
TaxonomyType.state: URLBuilder.static(Flavor.off, Environment.org)
59-
+ "/data/taxonomies/states.full.json",
60-
TaxonomyType.data_quality: URLBuilder.static(Flavor.off, Environment.org)
61-
+ "/data/taxonomies/data_quality.full.json",
62-
TaxonomyType.origin: URLBuilder.static(Flavor.off, Environment.org)
63-
+ "/data/taxonomies/origins.full.json",
64-
TaxonomyType.language: URLBuilder.static(Flavor.off, Environment.org)
65-
+ "/data/taxonomies/languages.full.json",
66-
TaxonomyType.other_nutritional_substance: URLBuilder.static(
67-
Flavor.off, Environment.org
68-
)
69-
+ "/data/taxonomies/other_nutritional_substances.full.json",
25+
Flavor.off: {
26+
TaxonomyType.category: URLBuilder.static(Flavor.off, Environment.org)
27+
+ "/data/taxonomies/categories.full.json",
28+
TaxonomyType.ingredient: URLBuilder.static(Flavor.off, Environment.org)
29+
+ "/data/taxonomies/ingredients.full.json",
30+
TaxonomyType.label: URLBuilder.static(Flavor.off, Environment.org)
31+
+ "/data/taxonomies/labels.full.json",
32+
TaxonomyType.brand: URLBuilder.static(Flavor.off, Environment.org)
33+
+ "/data/taxonomies/brands.full.json",
34+
TaxonomyType.packaging_shape: URLBuilder.static(Flavor.off, Environment.org)
35+
+ "/data/taxonomies/packaging_shapes.full.json",
36+
TaxonomyType.packaging_material: URLBuilder.static(Flavor.off, Environment.org)
37+
+ "/data/taxonomies/packaging_materials.full.json",
38+
TaxonomyType.packaging_recycling: URLBuilder.static(Flavor.off, Environment.org)
39+
+ "/data/taxonomies/packaging_recycling.full.json",
40+
TaxonomyType.country: URLBuilder.static(Flavor.off, Environment.org)
41+
+ "/data/taxonomies/countries.full.json",
42+
TaxonomyType.store: URLBuilder.static(Flavor.off, Environment.org)
43+
+ "/data/taxonomies/stores.full.json",
44+
TaxonomyType.nova_group: URLBuilder.static(Flavor.off, Environment.org)
45+
+ "/data/taxonomies/nova_groups.full.json",
46+
TaxonomyType.additive: URLBuilder.static(Flavor.off, Environment.org)
47+
+ "/data/taxonomies/additives.full.json",
48+
TaxonomyType.vitamin: URLBuilder.static(Flavor.off, Environment.org)
49+
+ "/data/taxonomies/vitamins.full.json",
50+
TaxonomyType.mineral: URLBuilder.static(Flavor.off, Environment.org)
51+
+ "/data/taxonomies/minerals.full.json",
52+
TaxonomyType.amino_acid: URLBuilder.static(Flavor.off, Environment.org)
53+
+ "/data/taxonomies/amino_acids.full.json",
54+
TaxonomyType.nucleotide: URLBuilder.static(Flavor.off, Environment.org)
55+
+ "/data/taxonomies/nucleotides.full.json",
56+
TaxonomyType.allergen: URLBuilder.static(Flavor.off, Environment.org)
57+
+ "/data/taxonomies/allergens.full.json",
58+
TaxonomyType.state: URLBuilder.static(Flavor.off, Environment.org)
59+
+ "/data/taxonomies/states.full.json",
60+
TaxonomyType.data_quality: URLBuilder.static(Flavor.off, Environment.org)
61+
+ "/data/taxonomies/data_quality.full.json",
62+
TaxonomyType.origin: URLBuilder.static(Flavor.off, Environment.org)
63+
+ "/data/taxonomies/origins.full.json",
64+
TaxonomyType.language: URLBuilder.static(Flavor.off, Environment.org)
65+
+ "/data/taxonomies/languages.full.json",
66+
TaxonomyType.other_nutritional_substance: URLBuilder.static(
67+
Flavor.off, Environment.org
68+
)
69+
+ "/data/taxonomies/other_nutritional_substances.full.json",
70+
},
71+
Flavor.obf: {
72+
TaxonomyType.category: URLBuilder.static(Flavor.obf, Environment.org)
73+
+ "/data/taxonomies/categories.full.json",
74+
TaxonomyType.ingredient: URLBuilder.static(Flavor.obf, Environment.org)
75+
+ "/data/taxonomies/ingredients.full.json",
76+
TaxonomyType.label: URLBuilder.static(Flavor.obf, Environment.org)
77+
+ "/data/taxonomies/labels.full.json",
78+
TaxonomyType.brand: URLBuilder.static(Flavor.obf, Environment.org)
79+
+ "/data/taxonomies/brands.full.json",
80+
TaxonomyType.allergen: URLBuilder.static(Flavor.obf, Environment.org)
81+
+ "/data/taxonomies/allergens.full.json",
82+
},
83+
Flavor.opff: {
84+
TaxonomyType.category: URLBuilder.static(Flavor.opff, Environment.org)
85+
+ "/data/taxonomies/categories.full.json",
86+
TaxonomyType.ingredient: URLBuilder.static(Flavor.opff, Environment.org)
87+
+ "/data/taxonomies/ingredients.full.json",
88+
},
89+
Flavor.opf: {
90+
TaxonomyType.category: URLBuilder.static(Flavor.opf, Environment.org)
91+
+ "/data/taxonomies/categories.full.json",
92+
TaxonomyType.label: URLBuilder.static(Flavor.opf, Environment.org)
93+
+ "/data/taxonomies/labels.full.json",
94+
TaxonomyType.brand: URLBuilder.static(Flavor.opf, Environment.org)
95+
+ "/data/taxonomies/brands.full.json",
96+
},
7097
}
7198

7299

@@ -367,29 +394,34 @@ def from_url(
367394
return cls.from_dict(data)
368395

369396
@classmethod
370-
def from_type(cls, taxonomy_type: TaxonomyType) -> "Taxonomy":
397+
def from_type(
398+
cls, taxonomy_type: TaxonomyType, flavor: Flavor = Flavor.off
399+
) -> "Taxonomy":
371400
"""Create a Taxonomy from a taxonomy file hosted online from a
372401
taxonomy type.
373402
374403
:param taxonomy_type: the taxonomy type
404+
:param flavor: The data source, defaults to Flavor.off
375405
:return: a Taxonomy
376406
"""
377-
url = TAXONOMY_URLS[TaxonomyType[taxonomy_type]]
407+
url = TAXONOMY_URLS[flavor][TaxonomyType[taxonomy_type]]
378408
return cls.from_url(url)
379409

380410

381411
def get_taxonomy(
382412
taxonomy_type: TaxonomyType | str,
413+
flavor: Flavor = Flavor.off,
383414
force_download: bool = False,
384415
download_newer: bool = False,
385416
cache_dir: Path | None = None,
386417
tmp_dir: Path | None = None,
387418
) -> Taxonomy:
388-
"""Return the taxonomy of the provided type.
419+
"""Return the taxonomy of the provided type & flavor.
389420
390421
The taxonomy file is downloaded and cached locally.
391422
392423
:param taxonomy_type: the requested taxonomy type
424+
:param flavor: The data source, defaults to Flavor.off
393425
:param force_download: if True, (re)download the taxonomy even if it was
394426
cached, defaults to False
395427
:param download_newer: if True, download the taxonomy if a more recent
@@ -403,11 +435,11 @@ def get_taxonomy(
403435
:return: a Taxonomy
404436
"""
405437
taxonomy_type = TaxonomyType[taxonomy_type]
406-
filename = f"{taxonomy_type.name}.json"
438+
filename = f"{flavor.name}-{taxonomy_type.name}.json"
407439

408440
cache_dir = DEFAULT_CACHE_DIR if cache_dir is None else cache_dir
409441
taxonomy_path = cache_dir / filename
410-
url = TAXONOMY_URLS[taxonomy_type]
442+
url = TAXONOMY_URLS[flavor][taxonomy_type]
411443

412444
if not should_download_file(url, taxonomy_path, force_download, download_newer):
413445
return Taxonomy.from_path(taxonomy_path)

0 commit comments

Comments
 (0)