127 lines
8.4 KiB
Python
127 lines
8.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Seed HerbAPI with common permaculture plant families and species via GBIF + API."""
|
|
import json, urllib.request, urllib.parse, time, sys
|
|
|
|
API = "http://herbapi01.corp.sub-net.at:8080/api/v1"
|
|
TOKEN = "km2WjhgyMTHlltwgch5TZADHQ-4uIg0NxBeowD-DHGk"
|
|
GBIF = "https://api.gbif.org/v1"
|
|
|
|
def api_post(path, data):
|
|
req = urllib.request.Request(f"{API}{path}",
|
|
data=json.dumps(data).encode(),
|
|
headers={"Content-Type": "application/json", "Authorization": f"Bearer {TOKEN}"})
|
|
try:
|
|
resp = urllib.request.urlopen(req)
|
|
return json.loads(resp.read())
|
|
except urllib.error.HTTPError as e:
|
|
print(f" ERR {e.code}: {e.read().decode()[:120]}", file=sys.stderr)
|
|
return None
|
|
|
|
def gbif_de_name(name):
|
|
"""Get German common name from GBIF."""
|
|
url = f"{GBIF}/species/match?name={urllib.parse.quote(name)}"
|
|
try:
|
|
match = json.loads(urllib.request.urlopen(url).read())
|
|
if not match.get("usageKey"): return None
|
|
url2 = f"{GBIF}/species/{match['usageKey']}/vernacularNames?limit=100"
|
|
data = json.loads(urllib.request.urlopen(url2).read())
|
|
for r in data.get("results", []):
|
|
if r.get("language") == "deu":
|
|
return r["vernacularName"]
|
|
except: pass
|
|
return None
|
|
|
|
FAMILIES = [
|
|
("Fabaceae", "Hülsenfrüchtler", "Legumes"),
|
|
("Rosaceae", "Rosengewächse", "Rose family"),
|
|
("Brassicaceae", "Kreuzblütler", "Cabbage family"),
|
|
("Apiaceae", "Doldenblütler", "Carrot family"),
|
|
("Lamiaceae", "Lippenblütler", "Mint family"),
|
|
("Asteraceae", "Korbblütler", "Daisy family"),
|
|
("Solanaceae", "Nachtschattengewächse", "Nightshade family"),
|
|
("Cucurbitaceae", "Kürbisgewächse", "Gourd family"),
|
|
("Poaceae", "Süßgräser", "Grass family"),
|
|
("Amaryllidaceae", "Amaryllisgewächse", "Amaryllis family"),
|
|
("Boraginaceae", "Raublattgewächse", "Borage family"),
|
|
("Adoxaceae", "Moschuskrautgewächse", "Moschatel family"),
|
|
("Betulaceae", "Birkengewächse", "Birch family"),
|
|
("Fagaceae", "Buchengewächse", "Beech family"),
|
|
("Juglandaceae", "Walnussgewächse", "Walnut family"),
|
|
("Caprifoliaceae", "Geißblattgewächse", "Honeysuckle family"),
|
|
("Grossulariaceae", "Stachelbeergewächse", "Gooseberry family"),
|
|
("Ericaceae", "Heidekrautgewächse", "Heath family"),
|
|
("Moraceae", "Maulbeergewächse", "Mulberry family"),
|
|
("Urticaceae", "Brennnesselgewächse", "Nettle family"),
|
|
("Malvaceae", "Malvengewächse", "Mallow family"),
|
|
("Polygonaceae", "Knöterichgewächse", "Buckwheat family"),
|
|
("Chenopodiaceae", "Gänsefußgewächse", "Goosefoot family"),
|
|
("Asparagaceae", "Spargelgewächse", "Asparagus family"),
|
|
("Plantaginaceae", "Wegerichgewächse", "Plantain family"),
|
|
]
|
|
|
|
SPECIES = [
|
|
("Sambucus nigra", "Adoxaceae", {"plant_layer": "understory", "nitrogen_fixer": False, "food_uses": "Flowers (cordial, fritters), berries (cooked — syrup, wine)", "medicinal_uses": "Cold/flu remedy, immune support, diaphoretic", "succession_stage": "secondary"}),
|
|
("Symphytum officinale", "Boraginaceae", {"plant_layer": "herbaceous", "dynamic_accumulator": True, "food_uses": "Young leaves (limited, contains pyrrolizidine alkaloids)", "medicinal_uses": "Wound healing, bone knitting (external only)", "other_uses": "Dynamic accumulator, mulch/compost activator, animal fodder"}),
|
|
("Trifolium pratense", "Fabaceae", {"plant_layer": "ground_cover", "nitrogen_fixer": True, "food_uses": "Flowers, young leaves", "medicinal_uses": "Respiratory, menopausal symptoms", "other_uses": "Green manure, nitrogen fixer, bee forage"}),
|
|
("Corylus avellana", "Betulaceae", {"plant_layer": "shrub", "food_uses": "Nuts", "other_uses": "Coppice wood, hedging, wildlife habitat", "succession_stage": "secondary"}),
|
|
("Ribes nigrum", "Grossulariaceae", {"plant_layer": "shrub", "food_uses": "Berries, leaves (tea)", "medicinal_uses": "High vitamin C, anti-inflammatory"}),
|
|
("Rubus idaeus", "Rosaceae", {"plant_layer": "shrub", "food_uses": "Berries, leaves (tea)", "medicinal_uses": "Leaf tea for pregnancy/digestion", "succession_stage": "pioneer"}),
|
|
("Urtica dioica", "Urticaceae", {"plant_layer": "herbaceous", "dynamic_accumulator": True, "food_uses": "Young leaves, seeds", "medicinal_uses": "Anti-inflammatory, prostate, allergies", "other_uses": "Compost activator, fibre, liquid fertiliser"}),
|
|
("Borago officinalis", "Boraginaceae", {"plant_layer": "herbaceous", "food_uses": "Flowers, young leaves", "other_uses": "Bee forage, companion plant", "attracts_pollinators": True}),
|
|
("Lavandula angustifolia", "Lamiaceae", {"plant_layer": "herbaceous", "food_uses": "Flowers", "medicinal_uses": "Calming, antiseptic, sleep aid", "other_uses": "Bee forage, pest repellent, fragrance", "attracts_pollinators": True}),
|
|
("Malus domestica", "Rosaceae", {"plant_layer": "canopy", "food_uses": "Fruit", "pollination_type": "Insect-pollinated"}),
|
|
("Prunus domestica", "Rosaceae", {"plant_layer": "canopy", "food_uses": "Fruit", "pollination_type": "Insect-pollinated"}),
|
|
("Juglans regia", "Juglandaceae", {"plant_layer": "canopy", "food_uses": "Nuts", "other_uses": "Timber, dye", "allelopathic": True}),
|
|
("Fragaria vesca", "Rosaceae", {"plant_layer": "ground_cover", "food_uses": "Berries, leaves (tea)", "ground_cover_quality": "Good"}),
|
|
("Allium ursinum", "Amaryllidaceae", {"plant_layer": "ground_cover", "food_uses": "Leaves, flowers, bulbs", "medicinal_uses": "Antimicrobial, blood pressure"}),
|
|
("Phacelia tanacetifolia", "Boraginaceae", {"plant_layer": "herbaceous", "other_uses": "Green manure, bee forage, cover crop", "attracts_pollinators": True}),
|
|
("Lupinus polyphyllus", "Fabaceae", {"plant_layer": "herbaceous", "nitrogen_fixer": True, "other_uses": "Nitrogen fixer, green manure, ornamental"}),
|
|
("Vicia faba", "Fabaceae", {"plant_layer": "herbaceous", "nitrogen_fixer": True, "food_uses": "Beans", "other_uses": "Nitrogen fixer, green manure"}),
|
|
("Solanum lycopersicum", "Solanaceae", {"plant_layer": "herbaceous", "food_uses": "Fruit"}),
|
|
("Cucurbita pepo", "Cucurbitaceae", {"plant_layer": "ground_cover", "food_uses": "Fruit, seeds, flowers"}),
|
|
("Beta vulgaris", "Chenopodiaceae", {"plant_layer": "herbaceous", "food_uses": "Roots, leaves"}),
|
|
("Daucus carota", "Apiaceae", {"plant_layer": "herbaceous", "food_uses": "Root"}),
|
|
("Calendula officinalis", "Asteraceae", {"plant_layer": "herbaceous", "food_uses": "Flowers", "medicinal_uses": "Wound healing, anti-inflammatory, skin care", "other_uses": "Companion plant, pest deterrent", "attracts_pollinators": True}),
|
|
("Melissa officinalis", "Lamiaceae", {"plant_layer": "herbaceous", "food_uses": "Leaves", "medicinal_uses": "Calming, antiviral, digestive", "attracts_pollinators": True}),
|
|
("Salvia officinalis", "Lamiaceae", {"plant_layer": "herbaceous", "food_uses": "Leaves", "medicinal_uses": "Sore throat, digestive, antimicrobial"}),
|
|
("Thymus vulgaris", "Lamiaceae", {"plant_layer": "ground_cover", "food_uses": "Leaves", "medicinal_uses": "Respiratory, antimicrobial, cough"}),
|
|
]
|
|
|
|
# Create families
|
|
print("=== Creating families ===")
|
|
family_map = {}
|
|
for sci, de, en in FAMILIES:
|
|
r = api_post("/families", {"name_scientific": sci, "name_de": de, "name_en": en})
|
|
if r:
|
|
family_map[sci] = r["id"]
|
|
print(f" ✓ {sci}")
|
|
time.sleep(0.05)
|
|
print(f"Created {len(family_map)} families\n")
|
|
|
|
# Create species
|
|
print("=== Creating species (with GBIF German names) ===")
|
|
created = 0
|
|
for sci_name, family_sci, extra in SPECIES:
|
|
fam_id = family_map.get(family_sci)
|
|
if not fam_id:
|
|
print(f" ✗ {sci_name} — family {family_sci} missing")
|
|
continue
|
|
de_name = gbif_de_name(sci_name)
|
|
data = {"name_scientific": sci_name, "name_de": de_name or "", "name_en": "", "family_id": fam_id, **extra}
|
|
r = api_post("/species", data)
|
|
if r:
|
|
created += 1
|
|
print(f" ✓ {sci_name} → {de_name or '(no DE name)'}")
|
|
time.sleep(0.15)
|
|
print(f"Created {created} species\n")
|
|
|
|
# Create suppliers
|
|
print("=== Creating suppliers ===")
|
|
for name, url, country, organic, demeter, notes in [
|
|
("Reinsaat", "https://www.reinsaat.at", "AT", True, True, "Austrian biodynamic seed producer, open-pollinated varieties"),
|
|
("Magic Garden Seeds", "https://www.magicgardenseeds.com", "DE", False, False, "Specialist seed shop with rare and heritage varieties"),
|
|
]:
|
|
r = api_post("/suppliers", {"name": name, "url": url, "country": country, "is_organic": organic, "is_demeter": demeter, "notes": notes})
|
|
if r: print(f" ✓ {name}")
|
|
print("\nDone!")
|