Coverage for cookbook/integration/recipekeeper.py: 22%
63 statements
« prev ^ index » next coverage.py v7.4.0, created at 2023-12-29 00:47 +0100
« prev ^ index » next coverage.py v7.4.0, created at 2023-12-29 00:47 +0100
1import re
2from io import BytesIO
3from zipfile import ZipFile
5from bs4 import BeautifulSoup
7from django.utils.translation import gettext as _
8from cookbook.helper.ingredient_parser import IngredientParser
9from cookbook.helper.recipe_url_import import iso_duration_to_minutes, parse_servings
10from cookbook.integration.integration import Integration
11from cookbook.models import Ingredient, Keyword, Recipe, Step
14class RecipeKeeper(Integration):
16 def import_file_name_filter(self, zip_info_object):
17 return re.match(r'^recipes.html$', zip_info_object.filename)
19 def split_recipe_file(self, file):
20 recipe_html = BeautifulSoup(file, 'html.parser')
21 return recipe_html.find_all('div', class_='recipe-details')
23 def get_recipe_from_file(self, file):
24 # 'file' comes is as a beautifulsoup object
25 recipe = Recipe.objects.create(name=file.find("h2", {"itemprop": "name"}).text.strip(), created_by=self.request.user, internal=True, space=self.request.space, )
27 # add 'Courses' and 'Categories' as keywords
28 for course in file.find_all("span", {"itemprop": "recipeCourse"}):
29 keyword, created = Keyword.objects.get_or_create(name=course.text, space=self.request.space)
30 recipe.keywords.add(keyword)
32 for category in file.find_all("meta", {"itemprop": "recipeCategory"}):
33 keyword, created = Keyword.objects.get_or_create(name=category.get("content"), space=self.request.space)
34 recipe.keywords.add(keyword)
36 try:
37 recipe.servings = parse_servings(file.find("span", {"itemprop": "recipeYield"}).text.strip())
38 recipe.working_time = iso_duration_to_minutes(file.find("span", {"meta": "prepTime"}).text.strip())
39 recipe.waiting_time = iso_duration_to_minutes(file.find("span", {"meta": "cookTime"}).text.strip())
40 recipe.save()
41 except AttributeError:
42 pass
44 step = Step.objects.create(instruction='', space=self.request.space, show_ingredients_table=self.request.user.userpreference.show_step_ingredients, )
46 ingredient_parser = IngredientParser(self.request, True)
47 for ingredient in file.find("div", {"itemprop": "recipeIngredients"}).findChildren("p"):
48 if ingredient.text == "":
49 continue
50 amount, unit, food, note = ingredient_parser.parse(ingredient.text.strip())
51 f = ingredient_parser.get_food(food)
52 u = ingredient_parser.get_unit(unit)
53 step.ingredients.add(Ingredient.objects.create(
54 food=f, unit=u, amount=amount, note=note, original_text=str(ingredient).replace('<p>', '').replace('</p>', ''), space=self.request.space,
55 ))
57 for s in file.find("div", {"itemprop": "recipeDirections"}).find_all("p"):
58 if s.text == "":
59 continue
60 step.instruction += s.text + ' \n'
61 step.save()
63 for s in file.find("div", {"itemprop": "recipeNotes"}).find_all("p"):
64 if s.text == "":
65 continue
66 step.instruction += s.text + ' \n'
67 step.save()
69 if file.find("span", {"itemprop": "recipeSource"}).text != '':
70 step.instruction += "\n\n" + _("Imported from") + ": " + file.find("span", {"itemprop": "recipeSource"}).text
71 step.save()
73 recipe.steps.add(step)
75 # import the Primary recipe image that is stored in the Zip
76 try:
77 for f in self.files:
78 if '.zip' in f['name']:
79 import_zip = ZipFile(f['file'])
80 self.import_recipe_image(recipe, BytesIO(import_zip.read(file.find("img", class_="recipe-photo").get("src"))), filetype='.jpeg')
81 except Exception as e:
82 print(recipe.name, ': failed to import image ', str(e))
84 return recipe
86 def get_file_from_recipe(self, recipe):
87 raise NotImplementedError('Method not implemented in storage integration')