Skip to content
This repository was archived by the owner on Aug 22, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 39 additions & 13 deletions reciperadar/models/recipes/direction.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from xml.etree import ElementTree

from reciperadar import db
from reciperadar.models.base import Storable
from reciperadar.models.recipes.appliance import DirectionAppliance
Expand Down Expand Up @@ -31,26 +33,50 @@ class RecipeDirection(Storable):
passive_deletes='all'
)

@staticmethod
def _build_item(item, category, category_class):
item_classes = set(item.attrib.get('class', '').split())
if 'equipment' not in item_classes:
return
if category not in item_classes:
return
doc = {category: item.text}
return category_class.from_doc(doc)

@staticmethod
def _parse_equipment(markup):
equipment = {
'appliances': [],
'utensils': [],
'vessels': [],
}
if not markup:
return equipment

category_classes = {
'appliances': DirectionAppliance,
'utensils': DirectionUtensil,
'vessels': DirectionVessel,
}

doc = ElementTree.fromstring(f'<xml>{markup}</xml>')
for item in doc.findall('mark'):
for category in equipment:
cls = category_classes[category]
obj = RecipeDirection._build_item(item, category[:-1], cls)
equipment[category].append(obj) if obj else None
return equipment

@staticmethod
def from_doc(doc, matches=None):
direction_id = doc.get('id') or RecipeDirection.generate_id()
equipment = RecipeDirection._parse_equipment(doc['markup'])
return RecipeDirection(
id=direction_id,
index=doc.get('index'), # TODO
description=doc['description'],
markup=doc.get('markup'),
appliances=[
DirectionAppliance.from_doc(appliance)
for appliance in doc.get('appliances', [])
],
utensils=[
DirectionUtensil.from_doc(utensil)
for utensil in doc.get('utensils', [])
],
vessels=[
DirectionVessel.from_doc(vessel)
for vessel in doc.get('vessels', [])
]
markup=doc['markup'],
**equipment
)

def to_doc(self):
Expand Down
20 changes: 5 additions & 15 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,11 @@ def raw_recipe_hit():
{
"index": 0,
"description": "place each skewer in the oven",
"appliances": [
{
"appliance": "oven"
}
],
"utensils": [
{
"utensil": "skewer"
}
],
"vessels": [
{
"vessel": "casserole dish"
}
]
"markup": (
"<mark class='action'>place</mark> each "
"<mark class='equipment utensil'>skewer</mark> in the "
"<mark class='equipment appliance'>oven</mark>"
)
}
],
"ingredients": [
Expand Down
1 change: 0 additions & 1 deletion tests/models/recipes/test_recipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ def test_recipe_from_doc(raw_recipe_hit):

assert recipe.directions[0].appliances[0].appliance == 'oven'
assert recipe.directions[0].utensils[0].utensil == 'skewer'
assert recipe.directions[0].vessels[0].vessel == 'casserole dish'

assert recipe.ingredients[0].product.product == 'one'
expected_contents = ['one', 'content-of-one', 'ancestor-of-one']
Expand Down