remove unused imports, variables and commented code

from tests
This commit is contained in:
smilerz 2023-09-13 13:08:26 -05:00
parent 78b1386a1c
commit 1f0cd58d7d
No known key found for this signature in database
GPG Key ID: 39444C7606D47126
48 changed files with 112 additions and 568 deletions

View File

@ -1,8 +1,7 @@
import os
import sys
from io import BytesIO
from PIL import Image
from io import BytesIO
def rescale_image_jpeg(image_object, base_width=1020):

View File

@ -116,12 +116,6 @@ class OpenDataImporter:
self._update_slug_cache(Unit, 'unit')
self._update_slug_cache(PropertyType, 'property')
# pref_unit_key = 'preferred_unit_metric'
# pref_shopping_unit_key = 'preferred_packaging_unit_metric'
# if not self.use_metric:
# pref_unit_key = 'preferred_unit_imperial'
# pref_shopping_unit_key = 'preferred_packaging_unit_imperial'
insert_list = []
update_list = []
update_field_list = []
@ -130,8 +124,6 @@ class OpenDataImporter:
insert_list.append({'data': {
'name': self.data[datatype][k]['name'],
'plural_name': self.data[datatype][k]['plural_name'] if self.data[datatype][k]['plural_name'] != '' else None,
# 'preferred_unit_id': self.slug_id_cache['unit'][self.data[datatype][k][pref_unit_key]],
# 'preferred_shopping_unit_id': self.slug_id_cache['unit'][self.data[datatype][k][pref_shopping_unit_key]],
'supermarket_category_id': self.slug_id_cache['category'][self.data[datatype][k]['store_category']],
'fdc_id': self.data[datatype][k]['fdc_id'] if self.data[datatype][k]['fdc_id'] != '' else None,
'open_data_slug': k,
@ -149,8 +141,6 @@ class OpenDataImporter:
id=existing_food_id,
name=self.data[datatype][k]['name'],
plural_name=self.data[datatype][k]['plural_name'] if self.data[datatype][k]['plural_name'] != '' else None,
# preferred_unit_id=self.slug_id_cache['unit'][self.data[datatype][k][pref_unit_key]],
# preferred_shopping_unit_id=self.slug_id_cache['unit'][self.data[datatype][k][pref_shopping_unit_key]],
supermarket_category_id=self.slug_id_cache['category'][self.data[datatype][k]['store_category']],
fdc_id=self.data[datatype][k]['fdc_id'] if self.data[datatype][k]['fdc_id'] != '' else None,
open_data_slug=k,
@ -189,7 +179,6 @@ class OpenDataImporter:
FoodProperty.objects.bulk_create(property_food_relation_list, ignore_conflicts=True, unique_fields=('food_id', 'property_id',))
# Automation.objects.bulk_create(alias_list, ignore_conflicts=True, unique_fields=('space', 'param_1', 'param_2',))
return insert_list + update_list
def import_conversion(self):
@ -197,7 +186,7 @@ class OpenDataImporter:
insert_list = []
for k in list(self.data[datatype].keys()):
# try catch here because somettimes key "k" is not set for he food cache
# try catch here because sometimes key "k" is not set for he food cache
try:
insert_list.append(UnitConversion(
base_amount=self.data[datatype][k]['base_amount'],

View File

@ -4,16 +4,16 @@ from django.conf import settings
from django.contrib import messages
from django.contrib.auth.decorators import user_passes_test
from django.core.cache import cache
from django.core.exceptions import ValidationError, ObjectDoesNotExist
from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.http import HttpResponseRedirect
from django.urls import reverse, reverse_lazy
from django.utils.translation import gettext as _
from oauth2_provider.contrib.rest_framework import TokenHasScope, TokenHasReadWriteScope
from oauth2_provider.contrib.rest_framework import TokenHasReadWriteScope, TokenHasScope
from oauth2_provider.models import AccessToken
from rest_framework import permissions
from rest_framework.permissions import SAFE_METHODS
from cookbook.models import ShareLink, Recipe, UserSpace
from cookbook.models import Recipe, ShareLink, UserSpace
def get_allowed_groups(groups_required):
@ -255,9 +255,6 @@ class CustomIsShared(permissions.BasePermission):
return request.user.is_authenticated
def has_object_permission(self, request, view, obj):
# # temporary hack to make old shopping list work with new shopping list
# if obj.__class__.__name__ in ['ShoppingList', 'ShoppingListEntry']:
# return is_object_shared(request.user, obj) or obj.created_by in list(request.user.get_shopping_share())
return is_object_shared(request.user, obj)
@ -322,7 +319,8 @@ class CustomRecipePermission(permissions.BasePermission):
def has_permission(self, request, view): # user is either at least a guest or a share link is given and the request is safe
share = request.query_params.get('share', None)
return ((has_group_permission(request.user, ['guest']) and request.method in SAFE_METHODS) or has_group_permission(request.user, ['user'])) or (share and request.method in SAFE_METHODS and 'pk' in view.kwargs)
return ((has_group_permission(request.user, ['guest']) and request.method in SAFE_METHODS) or has_group_permission(
request.user, ['user'])) or (share and request.method in SAFE_METHODS and 'pk' in view.kwargs)
def has_object_permission(self, request, view, obj):
share = request.query_params.get('share', None)
@ -332,7 +330,8 @@ class CustomRecipePermission(permissions.BasePermission):
if obj.private:
return ((obj.created_by == request.user) or (request.user in obj.shared.all())) and obj.space == request.space
else:
return ((has_group_permission(request.user, ['guest']) and request.method in SAFE_METHODS) or has_group_permission(request.user, ['user'])) and obj.space == request.space
return ((has_group_permission(request.user, ['guest']) and request.method in SAFE_METHODS)
or has_group_permission(request.user, ['user'])) and obj.space == request.space
class CustomUserPermission(permissions.BasePermission):
@ -361,7 +360,7 @@ class CustomTokenHasScope(TokenHasScope):
"""
def has_permission(self, request, view):
if type(request.auth) == AccessToken:
if isinstance(request.auth, AccessToken):
return super().has_permission(request, view)
else:
return request.user.is_authenticated
@ -375,7 +374,7 @@ class CustomTokenHasReadWriteScope(TokenHasReadWriteScope):
"""
def has_permission(self, request, view):
if type(request.auth) == AccessToken:
if isinstance(request.auth, AccessToken):
return super().has_permission(request, view)
else:
return True

View File

@ -14,7 +14,6 @@ from cookbook.models import (CookLog, CustomFilter, Food, Keyword, Recipe, Searc
from recipes import settings
# TODO create extensive tests to make sure ORs ANDs and various filters, sorting, etc work as expected
# TODO consider creating a simpleListRecipe API that only includes minimum of recipe info and minimal filtering
class RecipeSearch():
_postgres = settings.DATABASES['default']['ENGINE'] in ['django.db.backends.postgresql_psycopg2', 'django.db.backends.postgresql']
@ -162,7 +161,7 @@ class RecipeSearch():
else:
order = []
# TODO add userpreference for default sort order and replace '-favorite'
default_order = ['-name']
default_order = ['name']
# recent and new_recipe are always first; they float a few recipes to the top
if self._num_recent:
order += ['-recent']
@ -580,218 +579,3 @@ class RecipeSearch():
.annotate(sibling_onhand=Exists(sibling_onhand_subquery))
.filter(sibling_onhand=True)
)
# class RecipeFacet():
# class CacheEmpty(Exception):
# pass
# def __init__(self, request, queryset=None, hash_key=None, cache_timeout=3600):
# if hash_key is None and queryset is None:
# raise ValueError(_("One of queryset or hash_key must be provided"))
# self._request = request
# self._queryset = queryset
# self.hash_key = hash_key or str(hash(self._queryset.query))
# self._SEARCH_CACHE_KEY = f"recipes_filter_{self.hash_key}"
# self._cache_timeout = cache_timeout
# self._cache = caches['default'].get(self._SEARCH_CACHE_KEY, {})
# if self._cache is None and self._queryset is None:
# raise self.CacheEmpty("No queryset provided and cache empty")
# self.Keywords = self._cache.get('Keywords', None)
# self.Foods = self._cache.get('Foods', None)
# self.Books = self._cache.get('Books', None)
# self.Ratings = self._cache.get('Ratings', None)
# # TODO Move Recent to recipe annotation/serializer: requrires change in RecipeSearch(), RecipeSearchView.vue and serializer
# self.Recent = self._cache.get('Recent', None)
# if self._queryset is not None:
# self._recipe_list = list(
# self._queryset.values_list('id', flat=True))
# self._search_params = {
# 'keyword_list': self._request.query_params.getlist('keywords', []),
# 'food_list': self._request.query_params.getlist('foods', []),
# 'book_list': self._request.query_params.getlist('book', []),
# 'search_keywords_or': str2bool(self._request.query_params.get('keywords_or', True)),
# 'search_foods_or': str2bool(self._request.query_params.get('foods_or', True)),
# 'search_books_or': str2bool(self._request.query_params.get('books_or', True)),
# 'space': self._request.space,
# }
# elif self.hash_key is not None:
# self._recipe_list = self._cache.get('recipe_list', [])
# self._search_params = {
# 'keyword_list': self._cache.get('keyword_list', None),
# 'food_list': self._cache.get('food_list', None),
# 'book_list': self._cache.get('book_list', None),
# 'search_keywords_or': self._cache.get('search_keywords_or', None),
# 'search_foods_or': self._cache.get('search_foods_or', None),
# 'search_books_or': self._cache.get('search_books_or', None),
# 'space': self._cache.get('space', None),
# }
# self._cache = {
# **self._search_params,
# 'recipe_list': self._recipe_list,
# 'Ratings': self.Ratings,
# 'Recent': self.Recent,
# 'Keywords': self.Keywords,
# 'Foods': self.Foods,
# 'Books': self.Books
# }
# caches['default'].set(self._SEARCH_CACHE_KEY,
# self._cache, self._cache_timeout)
# def get_facets(self, from_cache=False):
# if from_cache:
# return {
# 'cache_key': self.hash_key or '',
# 'Ratings': self.Ratings or {},
# 'Recent': self.Recent or [],
# 'Keywords': self.Keywords or [],
# 'Foods': self.Foods or [],
# 'Books': self.Books or []
# }
# return {
# 'cache_key': self.hash_key,
# 'Ratings': self.get_ratings(),
# 'Recent': self.get_recent(),
# 'Keywords': self.get_keywords(),
# 'Foods': self.get_foods(),
# 'Books': self.get_books()
# }
# def set_cache(self, key, value):
# self._cache = {**self._cache, key: value}
# caches['default'].set(
# self._SEARCH_CACHE_KEY,
# self._cache,
# self._cache_timeout
# )
# def get_books(self):
# if self.Books is None:
# self.Books = []
# return self.Books
# def get_keywords(self):
# if self.Keywords is None:
# if self._search_params['search_keywords_or']:
# keywords = Keyword.objects.filter(
# space=self._request.space).distinct()
# else:
# keywords = Keyword.objects.filter(Q(recipe__in=self._recipe_list) | Q(
# depth=1)).filter(space=self._request.space).distinct()
# # set keywords to root objects only
# keywords = self._keyword_queryset(keywords)
# self.Keywords = [{**x, 'children': None}
# if x['numchild'] > 0 else x for x in list(keywords)]
# self.set_cache('Keywords', self.Keywords)
# return self.Keywords
# def get_foods(self):
# if self.Foods is None:
# # # if using an OR search, will annotate all keywords, otherwise, just those that appear in results
# if self._search_params['search_foods_or']:
# foods = Food.objects.filter(
# space=self._request.space).distinct()
# else:
# foods = Food.objects.filter(Q(ingredient__step__recipe__in=self._recipe_list) | Q(
# depth=1)).filter(space=self._request.space).distinct()
# # set keywords to root objects only
# foods = self._food_queryset(foods)
# self.Foods = [{**x, 'children': None}
# if x['numchild'] > 0 else x for x in list(foods)]
# self.set_cache('Foods', self.Foods)
# return self.Foods
# def get_ratings(self):
# if self.Ratings is None:
# if not self._request.space.demo and self._request.space.show_facet_count:
# if self._queryset is None:
# self._queryset = Recipe.objects.filter(
# id__in=self._recipe_list)
# rating_qs = self._queryset.annotate(rating=Round(Avg(Case(When(
# cooklog__created_by=self._request.user, then='cooklog__rating'), default=Value(0)))))
# self.Ratings = dict(Counter(r.rating for r in rating_qs))
# else:
# self.Rating = {}
# self.set_cache('Ratings', self.Ratings)
# return self.Ratings
# def get_recent(self):
# if self.Recent is None:
# # TODO make days of recent recipe a setting
# recent_recipes = ViewLog.objects.filter(created_by=self._request.user, space=self._request.space, created_at__gte=timezone.now() - timedelta(days=14)
# ).values_list('recipe__pk', flat=True)
# self.Recent = list(recent_recipes)
# self.set_cache('Recent', self.Recent)
# return self.Recent
# def add_food_children(self, id):
# try:
# food = Food.objects.get(id=id)
# nodes = food.get_ancestors()
# except Food.DoesNotExist:
# return self.get_facets()
# foods = self._food_queryset(food.get_children(), food)
# deep_search = self.Foods
# for node in nodes:
# index = next((i for i, x in enumerate(
# deep_search) if x["id"] == node.id), None)
# deep_search = deep_search[index]['children']
# index = next((i for i, x in enumerate(
# deep_search) if x["id"] == food.id), None)
# deep_search[index]['children'] = [
# {**x, 'children': None} if x['numchild'] > 0 else x for x in list(foods)]
# self.set_cache('Foods', self.Foods)
# return self.get_facets()
# def add_keyword_children(self, id):
# try:
# keyword = Keyword.objects.get(id=id)
# nodes = keyword.get_ancestors()
# except Keyword.DoesNotExist:
# return self.get_facets()
# keywords = self._keyword_queryset(keyword.get_children(), keyword)
# deep_search = self.Keywords
# for node in nodes:
# index = next((i for i, x in enumerate(
# deep_search) if x["id"] == node.id), None)
# deep_search = deep_search[index]['children']
# index = next((i for i, x in enumerate(deep_search)
# if x["id"] == keyword.id), None)
# deep_search[index]['children'] = [
# {**x, 'children': None} if x['numchild'] > 0 else x for x in list(keywords)]
# self.set_cache('Keywords', self.Keywords)
# return self.get_facets()
# def _recipe_count_queryset(self, field, depth=1, steplen=4):
# return Recipe.objects.filter(**{f'{field}__path__startswith': OuterRef('path'), f'{field}__depth__gte': depth}, id__in=self._recipe_list, space=self._request.space
# ).annotate(count=Coalesce(Func('pk', function='Count'), 0)).values('count')
# def _keyword_queryset(self, queryset, keyword=None):
# depth = getattr(keyword, 'depth', 0) + 1
# steplen = depth * Keyword.steplen
# if not self._request.space.demo and self._request.space.show_facet_count:
# return queryset.annotate(count=Coalesce(Subquery(self._recipe_count_queryset('keywords', depth, steplen)), 0)
# ).filter(depth=depth, count__gt=0
# ).values('id', 'name', 'count', 'numchild').order_by(Lower('name').asc())[:200]
# else:
# return queryset.filter(depth=depth).values('id', 'name', 'numchild').order_by(Lower('name').asc())
# def _food_queryset(self, queryset, food=None):
# depth = getattr(food, 'depth', 0) + 1
# steplen = depth * Food.steplen
# if not self._request.space.demo and self._request.space.show_facet_count:
# return queryset.annotate(count=Coalesce(Subquery(self._recipe_count_queryset('steps__ingredients__food', depth, steplen)), 0)
# ).filter(depth__lte=depth, count__gt=0
# ).values('id', 'name', 'count', 'numchild').order_by(Lower('name').asc())[:200]
# else:
# return queryset.filter(depth__lte=depth).values('id', 'name', 'numchild').order_by(Lower('name').asc())

View File

@ -408,16 +408,6 @@ def parse_time(recipe_time):
def parse_keywords(keyword_json, request):
keywords = []
automation_engine = AutomationEngine(request)
# keyword_aliases = {}
# retrieve keyword automation cache if it exists, otherwise build from database
# KEYWORD_CACHE_KEY = f'automation_keyword_alias_{space.pk}'
# if c := caches['default'].get(KEYWORD_CACHE_KEY, None):
# keyword_aliases = c
# caches['default'].touch(KEYWORD_CACHE_KEY, 30)
# else:
# for a in Automation.objects.filter(space=space, disabled=False, type=Automation.KEYWORD_ALIAS).only('param_1', 'param_2').order_by('order').all():
# keyword_aliases[a.param_1.lower()] = a.param_2
# caches['default'].set(KEYWORD_CACHE_KEY, keyword_aliases, 30)
# keywords as list
for kw in keyword_json:
@ -425,11 +415,6 @@ def parse_keywords(keyword_json, request):
# if alias exists use that instead
if len(kw) != 0:
# if keyword_aliases:
# try:
# kw = keyword_aliases[kw.lower()]
# except KeyError:
# pass
automation_engine.apply_keyword_automation(kw)
if k := Keyword.objects.filter(name=kw, space=request.space).first():
keywords.append({'label': str(k), 'name': k.name, 'id': k.id})

View File

@ -48,7 +48,6 @@ class ScopeMiddleware:
return views.no_groups(request)
request.space = user_space.space
# with scopes_disabled():
with scope(space=request.space):
return self.get_response(request)
else:

View File

@ -198,120 +198,3 @@ class RecipeShoppingEditor():
to_delete = self._shopping_list_recipe.entries.exclude(ingredient__in=ingredients)
ShoppingListEntry.objects.filter(id__in=to_delete).delete()
self._shopping_list_recipe = self.get_shopping_list_recipe(self.id, self.created_by, self.space)
# # TODO refactor as class
# def list_from_recipe(list_recipe=None, recipe=None, mealplan=None, servings=None, ingredients=None, created_by=None, space=None, append=False):
# """
# Creates ShoppingListRecipe and associated ShoppingListEntrys from a recipe or a meal plan with a recipe
# :param list_recipe: Modify an existing ShoppingListRecipe
# :param recipe: Recipe to use as list of ingredients. One of [recipe, mealplan] are required
# :param mealplan: alternatively use a mealplan recipe as source of ingredients
# :param servings: Optional: Number of servings to use to scale shoppinglist. If servings = 0 an existing recipe list will be deleted
# :param ingredients: Ingredients, list of ingredient IDs to include on the shopping list. When not provided all ingredients will be used
# :param append: If False will remove any entries not included with ingredients, when True will append ingredients to the shopping list
# """
# r = recipe or getattr(mealplan, 'recipe', None) or getattr(list_recipe, 'recipe', None)
# if not r:
# raise ValueError(_("You must supply a recipe or mealplan"))
# created_by = created_by or getattr(ShoppingListEntry.objects.filter(list_recipe=list_recipe).first(), 'created_by', None)
# if not created_by:
# raise ValueError(_("You must supply a created_by"))
# try:
# servings = float(servings)
# except (ValueError, TypeError):
# servings = getattr(mealplan, 'servings', 1.0)
# servings_factor = servings / r.servings
# shared_users = list(created_by.get_shopping_share())
# shared_users.append(created_by)
# if list_recipe:
# created = False
# else:
# list_recipe = ShoppingListRecipe.objects.create(recipe=r, mealplan=mealplan, servings=servings)
# created = True
# related_step_ing = []
# if servings == 0 and not created:
# list_recipe.delete()
# return []
# elif ingredients:
# ingredients = Ingredient.objects.filter(pk__in=ingredients, space=space)
# else:
# ingredients = Ingredient.objects.filter(step__recipe=r, food__ignore_shopping=False, space=space)
# if exclude_onhand := created_by.userpreference.mealplan_autoexclude_onhand:
# ingredients = ingredients.exclude(food__onhand_users__id__in=[x.id for x in shared_users])
# if related := created_by.userpreference.mealplan_autoinclude_related:
# # TODO: add levels of related recipes (related recipes of related recipes) to use when auto-adding mealplans
# related_recipes = r.get_related_recipes()
# for x in related_recipes:
# # related recipe is a Step serving size is driven by recipe serving size
# # TODO once/if Steps can have a serving size this needs to be refactored
# if exclude_onhand:
# # if steps are used more than once in a recipe or subrecipe - I don' think this results in the desired behavior
# related_step_ing += Ingredient.objects.filter(step__recipe=x, space=space).exclude(food__onhand_users__id__in=[x.id for x in shared_users]).values_list('id', flat=True)
# else:
# related_step_ing += Ingredient.objects.filter(step__recipe=x, space=space).values_list('id', flat=True)
# x_ing = []
# if ingredients.filter(food__recipe=x).exists():
# for ing in ingredients.filter(food__recipe=x):
# if exclude_onhand:
# x_ing = Ingredient.objects.filter(step__recipe=x, food__ignore_shopping=False, space=space).exclude(food__onhand_users__id__in=[x.id for x in shared_users])
# else:
# x_ing = Ingredient.objects.filter(step__recipe=x, food__ignore_shopping=False, space=space).exclude(food__ignore_shopping=True)
# for i in [x for x in x_ing]:
# ShoppingListEntry.objects.create(
# list_recipe=list_recipe,
# food=i.food,
# unit=i.unit,
# ingredient=i,
# amount=i.amount * Decimal(servings_factor),
# created_by=created_by,
# space=space,
# )
# # dont' add food to the shopping list that are actually recipes that will be added as ingredients
# ingredients = ingredients.exclude(food__recipe=x)
# add_ingredients = list(ingredients.values_list('id', flat=True)) + related_step_ing
# if not append:
# existing_list = ShoppingListEntry.objects.filter(list_recipe=list_recipe)
# # delete shopping list entries not included in ingredients
# existing_list.exclude(ingredient__in=ingredients).delete()
# # add shopping list entries that did not previously exist
# add_ingredients = set(add_ingredients) - set(existing_list.values_list('ingredient__id', flat=True))
# add_ingredients = Ingredient.objects.filter(id__in=add_ingredients, space=space)
# # if servings have changed, update the ShoppingListRecipe and existing Entries
# if servings <= 0:
# servings = 1
# if not created and list_recipe.servings != servings:
# update_ingredients = set(ingredients.values_list('id', flat=True)) - set(add_ingredients.values_list('id', flat=True))
# list_recipe.servings = servings
# list_recipe.save()
# for sle in ShoppingListEntry.objects.filter(list_recipe=list_recipe, ingredient__id__in=update_ingredients):
# sle.amount = sle.ingredient.amount * Decimal(servings_factor)
# sle.save()
# # add any missing Entries
# for i in [x for x in add_ingredients if x.food]:
# ShoppingListEntry.objects.create(
# list_recipe=list_recipe,
# food=i.food,
# unit=i.unit,
# ingredient=i,
# amount=i.amount * Decimal(servings_factor),
# created_by=created_by,
# space=space,
# )
# # return all shopping list items
# return list_recipe

View File

@ -2,13 +2,14 @@ import json
import re
from io import BytesIO, StringIO
from zipfile import ZipFile
from PIL import Image
from cookbook.helper.image_processing import get_filetype
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.helper.recipe_url_import import iso_duration_to_minutes
from cookbook.integration.integration import Integration
from cookbook.models import Ingredient, Keyword, Recipe, Step, NutritionInformation
from cookbook.models import Ingredient, Keyword, NutritionInformation, Recipe, Step
class NextcloudCookbook(Integration):
@ -51,7 +52,6 @@ class NextcloudCookbook(Integration):
ingredients_added = False
for s in recipe_json['recipeInstructions']:
instruction_text = ''
if 'text' in s:
step = Step.objects.create(
instruction=s['text'], name=s['name'], space=self.request.space, show_ingredients_table=self.request.user.userpreference.show_step_ingredients,
@ -91,7 +91,7 @@ class NextcloudCookbook(Integration):
if nutrition != {}:
recipe.nutrition = NutritionInformation.objects.create(**nutrition, space=self.request.space)
recipe.save()
except Exception as e:
except Exception:
pass
for f in self.files:

View File

@ -1,9 +1,11 @@
import json
from django.utils.translation import gettext as _
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.integration.integration import Integration
from cookbook.models import Ingredient, Recipe, Step, Keyword, Comment, CookLog
from django.utils.translation import gettext as _
from cookbook.models import Comment, CookLog, Ingredient, Keyword, Recipe, Step
class OpenEats(Integration):
@ -25,16 +27,16 @@ class OpenEats(Integration):
if file["source"] != '':
instructions += '\n' + _('Recipe source:') + f'[{file["source"]}]({file["source"]})'
cuisine_keyword, created = Keyword.objects.get_or_create(name="Cuisine", space=self.request.space)
cuisine_keyword, created = Keyword.objects.get_or_create(name="Cuisine", space=self.request.space)
if file["cuisine"] != '':
keyword, created = Keyword.objects.get_or_create(name=file["cuisine"].strip(), space=self.request.space)
keyword, created = Keyword.objects.get_or_create(name=file["cuisine"].strip(), space=self.request.space)
if created:
keyword.move(cuisine_keyword, pos="last-child")
recipe.keywords.add(keyword)
course_keyword, created = Keyword.objects.get_or_create(name="Course", space=self.request.space)
course_keyword, created = Keyword.objects.get_or_create(name="Course", space=self.request.space)
if file["course"] != '':
keyword, created = Keyword.objects.get_or_create(name=file["course"].strip(), space=self.request.space)
keyword, created = Keyword.objects.get_or_create(name=file["course"].strip(), space=self.request.space)
if created:
keyword.move(course_keyword, pos="last-child")
recipe.keywords.add(keyword)

View File

@ -90,7 +90,7 @@ class Paprika(Integration):
if validators.url(url, public=True):
response = requests.get(url)
self.import_recipe_image(recipe, BytesIO(response.content))
except:
except Exception:
if recipe_json.get("photo_data", None):
self.import_recipe_image(recipe, BytesIO(base64.b64decode(recipe_json['photo_data'])), filetype='.jpeg')

View File

@ -1,21 +1,11 @@
import json
from io import BytesIO
from re import match
from zipfile import ZipFile
import asyncio
from pyppeteer import launch
from rest_framework.renderers import JSONRenderer
from cookbook.helper.image_processing import get_filetype
from cookbook.integration.integration import Integration
from cookbook.serializer import RecipeExportSerializer
from cookbook.models import ExportLog
from asgiref.sync import sync_to_async
import django.core.management.commands.runserver as runserver
import logging
from asgiref.sync import sync_to_async
from pyppeteer import launch
from cookbook.integration.integration import Integration
class PDFexport(Integration):
@ -42,7 +32,6 @@ class PDFexport(Integration):
}
}
files = []
for recipe in recipes:
@ -50,20 +39,18 @@ class PDFexport(Integration):
await page.emulateMedia('print')
await page.setCookie(cookies)
await page.goto('http://'+cmd.default_addr+':'+cmd.default_port+'/view/recipe/'+str(recipe.id), {'waitUntil': 'domcontentloaded'})
await page.waitForSelector('#printReady');
await page.goto('http://' + cmd.default_addr + ':' + cmd.default_port + '/view/recipe/' + str(recipe.id), {'waitUntil': 'domcontentloaded'})
await page.waitForSelector('#printReady')
files.append([recipe.name + '.pdf', await page.pdf(options)])
await page.close();
await page.close()
el.exported_recipes += 1
el.msg += self.get_recipe_processed_msg(recipe)
await sync_to_async(el.save, thread_sensitive=True)()
await browser.close()
return files
def get_files_from_recipes(self, recipes, el, cookie):
return asyncio.run(self.get_files_from_recipes_async(recipes, el, cookie))

View File

@ -2,12 +2,10 @@ import base64
from io import BytesIO
from xml import etree
from lxml import etree
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.helper.recipe_url_import import parse_time, parse_servings, parse_servings_text
from cookbook.helper.recipe_url_import import parse_servings, parse_servings_text
from cookbook.integration.integration import Integration
from cookbook.models import Ingredient, Recipe, Step, Keyword
from cookbook.models import Ingredient, Keyword, Recipe, Step
class Rezeptsuitede(Integration):
@ -61,14 +59,14 @@ class Rezeptsuitede(Integration):
try:
k, created = Keyword.objects.get_or_create(name=recipe_xml.find('head').find('cat').text.strip(), space=self.request.space)
recipe.keywords.add(k)
except Exception as e:
except Exception:
pass
recipe.save()
try:
self.import_recipe_image(recipe, BytesIO(base64.b64decode(recipe_xml.find('head').find('picbin').text)), filetype='.jpeg')
except:
except BaseException:
pass
return recipe

View File

@ -60,8 +60,8 @@ class RezKonv(Integration):
def split_recipe_file(self, file):
recipe_list = []
current_recipe = ''
encoding_list = ['windows-1250',
'latin-1'] # TODO build algorithm to try trough encodings and fail if none work, use for all importers
# TODO build algorithm to try trough encodings and fail if none work, use for all importers
# encoding_list = ['windows-1250', 'latin-1']
encoding = 'windows-1250'
for fl in file.readlines():
try:

View File

@ -59,11 +59,11 @@ class Saffron(Integration):
def get_file_from_recipe(self, recipe):
data = "Title: "+recipe.name if recipe.name else ""+"\n"
data += "Description: "+recipe.description if recipe.description else ""+"\n"
data = "Title: " + recipe.name if recipe.name else "" + "\n"
data += "Description: " + recipe.description if recipe.description else "" + "\n"
data += "Source: \n"
data += "Original URL: \n"
data += "Yield: "+str(recipe.servings)+"\n"
data += "Yield: " + str(recipe.servings) + "\n"
data += "Cookbook: \n"
data += "Section: \n"
data += "Image: \n"
@ -78,13 +78,13 @@ class Saffron(Integration):
data += "Ingredients: \n"
for ingredient in recipeIngredient:
data += ingredient+"\n"
data += ingredient + "\n"
data += "Instructions: \n"
for instruction in recipeInstructions:
data += instruction+"\n"
data += instruction + "\n"
return recipe.name+'.txt', data
return recipe.name + '.txt', data
def get_files_from_recipes(self, recipes, el, cookie):
files = []

View File

@ -1294,7 +1294,7 @@ class UserFile(ExportModelOperationsMixin('user_files'), models.Model, Permissio
def is_image(self):
try:
img = Image.open(self.file.file.file)
Image.open(self.file.file.file)
return True
except Exception:
return False

View File

@ -208,7 +208,7 @@ class UserFileSerializer(serializers.ModelSerializer):
def get_preview_link(self, obj):
try:
img = Image.open(obj.file.file.file)
Image.open(obj.file.file.file)
return self.context['request'].build_absolute_uri(obj.file.url)
except Exception:
traceback.print_exc()
@ -256,7 +256,7 @@ class UserFileViewSerializer(serializers.ModelSerializer):
def get_preview_link(self, obj):
try:
img = Image.open(obj.file.file.file)
Image.open(obj.file.file.file)
return self.context['request'].build_absolute_uri(obj.file.url)
except Exception:
traceback.print_exc()

View File

@ -7,8 +7,6 @@ from django.utils import timezone
from django_scopes import scopes_disabled
from oauth2_provider.models import AccessToken
from cookbook.models import ViewLog
LIST_URL = 'api:accesstoken-list'
DETAIL_URL = 'api:accesstoken-detail'

View File

@ -35,11 +35,6 @@ register(FoodFactory, 'obj_3', space=LazyFixture('space_2'))
register(SupermarketCategoryFactory, 'cat_1', space=LazyFixture('space_1'))
# @pytest.fixture
# def true():
# return True
@pytest.fixture
def false():
return False

View File

@ -1,13 +1,3 @@
# test create
# test create units
# test amounts
# test create wrong space
# test sharing
# test delete
# test delete checked (nothing should happen)
# test delete not shared (nothing happens)
# test delete shared
import json
import pytest
@ -15,7 +5,6 @@ from django.contrib import auth
from django.urls import reverse
from django_scopes import scope, scopes_disabled
from cookbook.models import Food, ShoppingListEntry
from cookbook.tests.factories import FoodFactory
SHOPPING_LIST_URL = 'api:shoppinglistentry-list'
@ -80,8 +69,8 @@ def test_shopping_food_share(u1_s1, u2_s1, food, space_1):
user1 = auth.get_user(u1_s1)
user2 = auth.get_user(u2_s1)
food2 = FoodFactory(space=space_1)
r = u1_s1.put(reverse(SHOPPING_FOOD_URL, args={food.id}))
r = u2_s1.put(reverse(SHOPPING_FOOD_URL, args={food2.id}))
u1_s1.put(reverse(SHOPPING_FOOD_URL, args={food.id}))
u2_s1.put(reverse(SHOPPING_FOOD_URL, args={food2.id}))
sl_1 = json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)
sl_2 = json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)
assert len(sl_1) == 1

View File

@ -2,13 +2,10 @@ import json
import pytest
from django.contrib import auth
from django.contrib.auth.models import AnonymousUser
from django.db.models import OuterRef, Subquery
from django.urls import reverse
from django_scopes import scopes_disabled
from cookbook.helper.permission_helper import switch_user_active_space
from cookbook.models import Ingredient, Step, InviteLink, UserSpace
from cookbook.models import InviteLink
LIST_URL = 'api:invitelink-list'
DETAIL_URL = 'api:invitelink-detail'

View File

@ -25,6 +25,7 @@ if (Keyword.node_order_by):
else:
node_location = 'last-child'
@pytest.fixture()
def obj_1(space_1):
return Keyword.objects.get_or_create(name='test_1', space=space_1)[0]

View File

@ -6,7 +6,7 @@ from django.contrib import auth
from django.urls import reverse
from django_scopes import scope, scopes_disabled
from cookbook.models import Food, MealPlan, MealType
from cookbook.models import MealPlan, MealType
from cookbook.tests.factories import RecipeFactory
LIST_URL = 'api:mealplan-list'
@ -149,7 +149,7 @@ def test_add_with_shopping(u1_s1, meal_type):
space = meal_type.space
with scope(space=space):
recipe = RecipeFactory.create(space=space)
r = u1_s1.post(
u1_s1.post(
reverse(LIST_URL),
{'recipe': {'id': recipe.id, 'name': recipe.name, 'keywords': []}, 'meal_type': {'id': meal_type.id, 'name': meal_type.name},
'from_date': (datetime.now()).strftime("%Y-%m-%d"), 'to_date': (datetime.now()).strftime("%Y-%m-%d"), 'servings': 1, 'title': 'test', 'shared': [], 'addshopping': True},

View File

@ -5,7 +5,7 @@ from django.contrib import auth
from django.urls import reverse
from django_scopes import scopes_disabled
from cookbook.models import Food, MealType
from cookbook.models import MealType
LIST_URL = 'api:mealtype-list'
DETAIL_URL = 'api:mealtype-detail'

View File

@ -1,11 +1,10 @@
import json
import pytest
from django.contrib import auth
from django.urls import reverse
from django_scopes import scopes_disabled
from cookbook.models import Food, MealType, PropertyType, Property
from cookbook.models import MealType, Property, PropertyType
LIST_URL = 'api:property-list'
DETAIL_URL = 'api:property-detail'

View File

@ -1,11 +1,10 @@
import json
import pytest
from django.contrib import auth
from django.urls import reverse
from django_scopes import scopes_disabled
from cookbook.models import Food, MealType, PropertyType
from cookbook.models import MealType, PropertyType
LIST_URL = 'api:propertytype-list'
DETAIL_URL = 'api:propertytype-detail'

View File

@ -67,7 +67,8 @@ def test_share_permission(recipe_1_s1, u1_s1, u1_s2, u2_s1, a_u):
share = ShareLink.objects.filter(recipe=recipe_1_s1).first()
assert a_u.get(reverse(DETAIL_URL, args=[recipe_1_s1.pk]) + f'?share={share.uuid}').status_code == 200
assert u1_s1.get(reverse(DETAIL_URL, args=[recipe_1_s1.pk]) + f'?share={share.uuid}').status_code == 200
assert u1_s2.get(reverse(DETAIL_URL, args=[recipe_1_s1.pk]) + f'?share={share.uuid}').status_code == 404 # TODO fix in https://github.com/TandoorRecipes/recipes/issues/1238
# TODO fix in https://github.com/TandoorRecipes/recipes/issues/1238
assert u1_s2.get(reverse(DETAIL_URL, args=[recipe_1_s1.pk]) + f'?share={share.uuid}').status_code == 404
recipe_1_s1.created_by = auth.get_user(u1_s1)
recipe_1_s1.private = True
@ -100,7 +101,6 @@ def test_update(arg, request, recipe_1_s1):
j,
content_type='application/json'
)
response = json.loads(r.content)
assert r.status_code == arg[1]
if r.status_code == 200:
validate_recipe(j, json.loads(r.content))

View File

@ -48,8 +48,6 @@ def test_list_filter(obj_1, obj_2, u1_s1):
assert r.status_code == 200
response = json.loads(r.content)
assert len(response) == 2
# RecipeBooks model is unsorted - this isn't a reliable test
# assert response[0]['name'] == obj_1.name
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?limit=1').content)
assert len(response) == 1

View File

@ -1,11 +1,9 @@
import json
import factory
import pytest
from django.contrib import auth
from django.urls import reverse
from django_scopes import scopes_disabled
from pytest_factoryboy import LazyFixture, register
from cookbook.tests.factories import RecipeFactory
@ -18,7 +16,7 @@ def recipe(request, space_1, u1_s1):
params = request.param # request.param is a magic variable
except AttributeError:
params = {}
step_recipe = params.get('steps__count', 1)
# step_recipe = params.get('steps__count', 1) # TODO add tests for step recipes
steps__recipe_count = params.get('steps__recipe_count', 0)
steps__food_recipe_count = params.get('steps__food_recipe_count', {})
created_by = params.get('created_by', auth.get_user(u1_s1))
@ -26,6 +24,7 @@ def recipe(request, space_1, u1_s1):
return RecipeFactory.create(
steps__recipe_count=steps__recipe_count,
steps__food_recipe_count=steps__food_recipe_count,
# steps__step_recipe=step_recipe, # TODO add tests for step recipes
created_by=created_by,
space=space_1,
)
@ -56,7 +55,7 @@ def test_get_related_recipes(request, arg, recipe, related_count, u1_s1, space_2
({'steps__food_recipe_count': {'step': 0, 'count': 1}}), # shopping list from recipe with food recipe
({'steps__food_recipe_count': {'step': 0, 'count': 1}, 'steps__recipe_count': 1}), # shopping list from recipe with StepRecipe and food recipe
], indirect=['recipe'])
def test_related_mixed_space(request, recipe, u1_s2, space_2):
def test_related_mixed_space(request, recipe, u1_s2, space_2):
with scopes_disabled():
recipe.space = space_2
recipe.save()

View File

@ -5,7 +5,7 @@ from django.contrib import auth
from django.urls import reverse
from django_scopes import scopes_disabled
from cookbook.models import RecipeBook, ShoppingList, Storage, Sync, SyncLog
from cookbook.models import ShoppingList
LIST_URL = 'api:shoppinglist-list'
DETAIL_URL = 'api:shoppinglist-detail'

View File

@ -2,7 +2,6 @@ import json
import pytest
from django.contrib import auth
from django.forms import model_to_dict
from django.urls import reverse
from django_scopes import scopes_disabled

View File

@ -1,14 +1,11 @@
import json
from datetime import timedelta
import factory
import pytest
from django.contrib import auth
from django.forms import model_to_dict
from django.urls import reverse
from django.utils import timezone
from django_scopes import scopes_disabled
from pytest_factoryboy import LazyFixture, register
from cookbook.models import ShoppingListEntry
from cookbook.tests.factories import ShoppingListEntryFactory
@ -46,7 +43,7 @@ def test_list_permission(arg, request):
assert c.get(reverse(LIST_URL)).status_code == arg[1]
def test_list_space(sle, u1_s1, u1_s2, space_2):
def test_list_space(sle, u1_s1, u1_s2, space_2):
assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 10
assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 0
@ -169,7 +166,7 @@ def test_sharing(request, shared, count, sle_2, sle, u1_s1):
assert len(r) == count
# count unchecked entries
if not x.status_code == 404:
count = count-1
count = count - 1
assert [x['checked'] for x in r].count(False) == count
# test shared user can delete
x = shared_client.delete(
@ -182,13 +179,12 @@ def test_sharing(request, shared, count, sle_2, sle, u1_s1):
assert len(r) == count
# count unchecked entries
if not x.status_code == 404:
count = count-1
count = count - 1
assert [x['checked'] for x in r].count(False) == count
def test_completed(sle, u1_s1):
# check 1 entry
#
u1_s1.patch(
reverse(DETAIL_URL, args={sle[0].id}),
{'checked': True},
@ -199,7 +195,7 @@ def test_completed(sle, u1_s1):
# count unchecked entries
assert [x['checked'] for x in r].count(False) == 9
# confirm completed_at is populated
assert [(x['completed_at'] != None) for x in r if x['checked']].count(True) == 1
assert [(x['completed_at'] is not None) for x in r if x['checked']].count(True) == 1
assert len(json.loads(u1_s1.get(f'{reverse(LIST_URL)}?checked=0').content)) == 9
assert len(json.loads(u1_s1.get(f'{reverse(LIST_URL)}?checked=1').content)) == 1
@ -213,7 +209,7 @@ def test_completed(sle, u1_s1):
r = json.loads(u1_s1.get(reverse(LIST_URL)).content)
assert [x['checked'] for x in r].count(False) == 10
# confirm completed_at value cleared
assert [(x['completed_at'] != None) for x in r if x['checked']].count(True) == 0
assert [(x['completed_at'] is not None) for x in r if x['checked']].count(True) == 0
def test_recent(sle, u1_s1):

View File

@ -2,11 +2,10 @@ import json
import pytest
from django.contrib import auth
from django.forms import model_to_dict
from django.urls import reverse
from django_scopes import scopes_disabled
from cookbook.models import RecipeBook, Storage, Sync, SyncLog, ShoppingList, ShoppingListEntry, Food, ShoppingListRecipe
from cookbook.models import ShoppingList, ShoppingListRecipe
LIST_URL = 'api:shoppinglistrecipe-list'
DETAIL_URL = 'api:shoppinglistrecipe-detail'
@ -21,7 +20,7 @@ def obj_1(space_1, u1_s1, recipe_1_s1):
@pytest.fixture
def obj_2(space_1, u1_s1,recipe_1_s1):
def obj_2(space_1, u1_s1, recipe_1_s1):
r = ShoppingListRecipe.objects.create(recipe=recipe_1_s1, servings=1)
s = ShoppingList.objects.create(created_by=auth.get_user(u1_s1), space=space_1, )
s.recipes.add(r)

View File

@ -246,8 +246,6 @@ def test_shopping_recipe_mixed_authors(u1_s1, u2_s1, space_1):
@pytest.mark.parametrize("recipe", [{'steps__ingredients__header': 1}], indirect=['recipe'])
def test_shopping_with_header_ingredient(u1_s1, recipe):
# with scope(space=recipe.space):
# recipe.step_set.first().ingredient_set.add(IngredientFactory(ingredients__header=1))
u1_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}))
assert len(json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)) == 10
assert len(json.loads(

View File

@ -2,12 +2,9 @@ import json
import pytest
from django.contrib import auth
from django.db.models import OuterRef, Subquery
from django.urls import reverse
from django_scopes import scopes_disabled
from cookbook.models import Ingredient, Step
LIST_URL = 'api:space-list'
DETAIL_URL = 'api:space-detail'

View File

@ -5,7 +5,7 @@ from django.contrib import auth
from django.urls import reverse
from django_scopes import scopes_disabled
from cookbook.models import RecipeBook, Storage, Sync
from cookbook.models import Storage
LIST_URL = 'api:storage-list'
DETAIL_URL = 'api:storage-detail'

View File

@ -1,11 +1,10 @@
import json
import pytest
from django.contrib import auth
from django.urls import reverse
from django_scopes import scopes_disabled
from cookbook.models import RecipeBook, Supermarket
from cookbook.models import Supermarket
LIST_URL = 'api:supermarket-list'
DETAIL_URL = 'api:supermarket-detail'
@ -48,7 +47,6 @@ def test_list_filter(obj_1, obj_2, u1_s1):
assert r.status_code == 200
response = json.loads(r.content)
assert len(response) == 2
# assert response[0]['name'] == obj_1.name # assuming an order when it's not always valid
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?limit=1').content)
assert len(response) == 1

View File

@ -5,7 +5,7 @@ from django.contrib import auth
from django.urls import reverse
from django_scopes import scopes_disabled
from cookbook.models import RecipeBook, Storage, Sync
from cookbook.models import Storage, Sync
LIST_URL = 'api:sync-list'
DETAIL_URL = 'api:sync-detail'

View File

@ -5,7 +5,7 @@ from django.contrib import auth
from django.urls import reverse
from django_scopes import scopes_disabled
from cookbook.models import Food, MealType, UnitConversion
from cookbook.models import MealType, UnitConversion
from cookbook.tests.conftest import get_random_food, get_random_unit
LIST_URL = 'api:unitconversion-list'

View File

@ -1,7 +1,6 @@
import json
import pytest
from django.contrib import auth
from django.urls import reverse
@ -77,7 +76,7 @@ def test_user_retrieve(arg, request, u1_s1):
assert r.status_code == arg[1]
def test_user_update(u1_s1, u2_s1,u1_s2):
def test_user_update(u1_s1, u2_s1, u1_s2):
# can update own user
r = u1_s1.patch(
reverse(

View File

@ -120,7 +120,6 @@ def test_default_inherit_fields(u1_s1, u1_s2, space_1, space_2):
r = u1_s1.get(
reverse(DETAIL_URL, args={auth.get_user(u1_s1).id}),
)
#assert len([x['field'] for x in json.loads(r.content)['food_inherit_default']]) == 0
# inherit all possible fields
with scope(space=space_1):

View File

@ -2,12 +2,9 @@ import json
import pytest
from django.contrib import auth
from django.db.models import OuterRef, Subquery
from django.urls import reverse
from django_scopes import scopes_disabled
from cookbook.models import Ingredient, Step
LIST_URL = 'api:userspace-list'
DETAIL_URL = 'api:userspace-detail'

View File

@ -36,18 +36,6 @@ def enable_db_access_for_all_tests(db):
pass
# @pytest.fixture()
# def space_1():
# with scopes_disabled():
# return Space.objects.get_or_create(name='space_1')[0]
# @pytest.fixture()
# def space_2():
# with scopes_disabled():
# return Space.objects.get_or_create(name='space_2')[0]
# ---------------------- OBJECT FIXTURES ---------------------
def get_random_recipe(space_1, u1_s1):
@ -124,7 +112,7 @@ def validate_recipe(expected, recipe):
# file and url are metadata not related to the recipe
[expected.pop(k) for k in ['file', 'url'] if k in expected]
# if a key is a list remove it to deal with later
lists = [k for k, v in expected.items() if type(v) == list]
lists = [k for k, v in expected.items() if isinstance(v, list)]
for k in lists:
expected_lists[k] = expected.pop(k)
target_lists[k] = recipe.pop(k)
@ -157,7 +145,7 @@ def dict_compare(d1, d2, details=False):
d1_keys = set(d1.keys())
d2_keys = set(d2.keys())
shared = d1_keys.intersection(d2_keys)
sub_dicts = [i for i, j in d1.items() if type(j) == dict]
sub_dicts = [i for i, j in d1.items() if isinstance(j, dict)]
not_dicts = shared - set(sub_dicts)
added = d1_keys - d2_keys
removed = d2_keys - d1_keys

View File

@ -1,4 +1,5 @@
import inspect
from datetime import date
from decimal import Decimal
@ -11,12 +12,6 @@ from pytest_factoryboy import register
from cookbook.models import UserSpace
# this code will run immediately prior to creating the model object useful when you want a reverse relationship
# log = factory.RelatedFactory(
# UserLogFactory,
# factory_related_name='user',
# action=models.UserLog.ACTION_CREATE,
# )
faker = FakerFactory.create()
@ -96,7 +91,6 @@ class SupermarketCategoryFactory(factory.django.DjangoModelFactory):
django_get_or_create = ('name', 'space',)
# @factory.django.mute_signals(post_save)
@register
class FoodFactory(factory.django.DjangoModelFactory):
"""Food factory."""
@ -451,17 +445,6 @@ class RecipeFactory(factory.django.DjangoModelFactory):
for step in extracted:
self.steps.add(step)
# image = models.ImageField(upload_to='recipes/', blank=True, null=True) #TODO test recipe image api https://factoryboy.readthedocs.io/en/stable/orms.html#factory.django.ImageField
# storage = models.ForeignKey(
# Storage, on_delete=models.PROTECT, blank=True, null=True
# )
# file_uid = models.CharField(max_length=256, default="", blank=True)
# file_path = models.CharField(max_length=512, default="", blank=True)
# link = models.CharField(max_length=512, null=True, blank=True)
# cors_link = models.CharField(max_length=1024, null=True, blank=True)
# nutrition = models.ForeignKey(NutritionInformation, blank=True, null=True, on_delete=models.CASCADE)
# updated_at = models.DateTimeField(auto_now=True)
class Meta:
model = 'cookbook.Recipe'

View File

@ -2235,41 +2235,41 @@ THE_SPRUCE_EATS = {
"image": "https://www.thespruceeats.com/thmb/X_emapo3nNw6ASJctdNpYycYFtM=/940x0/filters:no_upscale():max_bytes(150000):strip_icc()/creamy-potato-soup-with-ham-3059797-stovetop-step-12-99dc3bf1962c4e26a2d225ee3c25ecad.jpg",
"source_url": "https://www.thespruceeats.com/creamy-potato-soup-with-ham-3059797",
"keywords": [
{
"label": "soup",
"name": "soup",
"id": 18,
},
{
"label": "lunch",
"name": "lunch",
},
"label": "soup",
"name": "soup",
"id": 18,
},
{
"label": "entree",
"name": "entree",
},
"label": "lunch",
"name": "lunch",
},
{
"label": "side dish",
"name": "side dish",
"id": 14,
},
"label": "entree",
"name": "entree",
},
{
"label": "www.thespruceeats.com",
"name": "www.thespruceeats.com",
},
"label": "side dish",
"name": "side dish",
"id": 14,
},
{
"label": "southern",
"name": "southern",
"id": 27,
},
"label": "www.thespruceeats.com",
"name": "www.thespruceeats.com",
},
{
"label": "cheddar",
"name": "cheddar",
},
"label": "southern",
"name": "southern",
"id": 27,
},
{
"label": "dinner",
"name": "dinner",
}
"label": "cheddar",
"name": "cheddar",
},
{
"label": "dinner",
"name": "dinner",
}
],
"steps": [
{

View File

@ -1,11 +1,12 @@
from decimal import Decimal
from django.contrib import auth
from django.core.cache import caches
from django_scopes import scopes_disabled
from decimal import Decimal
from cookbook.helper.cache_helper import CacheHelper
from cookbook.helper.property_helper import FoodPropertyHelper
from cookbook.models import Unit, Food, PropertyType, Property, Recipe, Step, UnitConversion, Property
from cookbook.models import Food, Property, PropertyType, Recipe, Step, Unit, UnitConversion
def test_food_property(space_1, space_2, u1_s1):
@ -125,5 +126,3 @@ def test_food_property(space_1, space_2, u1_s1):
property_values = FoodPropertyHelper(space_1).calculate_recipe_properties(recipe_2)
assert property_fat.id not in property_values

View File

@ -1,6 +1,5 @@
import pytest
from django.contrib import auth
from django.urls import reverse
from django_scopes import scope
from cookbook.helper.recipe_search import RecipeSearch

View File

@ -1,13 +1,10 @@
import pytest
from django.contrib import auth
from django.contrib.auth.models import Group
from django.urls import reverse
from django_scopes import scopes_disabled
from cookbook.forms import ImportExportBase
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.helper.permission_helper import has_group_permission, is_space_owner, switch_user_active_space, is_object_owner
from cookbook.models import ExportLog, UserSpace, Food, Space, Comment, RecipeBook, RecipeBookEntry
from cookbook.helper.permission_helper import (has_group_permission, is_object_owner,
is_space_owner, switch_user_active_space)
from cookbook.models import Food, RecipeBook, RecipeBookEntry, Space, UserSpace
def test_has_group_permission(u1_s1, a_u, space_2):

View File

@ -1,7 +1,4 @@
import pytest
from cookbook.models import Recipe
from django.contrib import auth
from django.urls import reverse
@ -28,7 +25,6 @@ def test_external_link_permission(arg, request, ext_recipe_1_s1):
['u1_s2', 404],
['a1_s2', 404],
])
def test_external_link_permission(arg, request, ext_recipe_1_s1):
def test_external_file_permission(arg, request, ext_recipe_1_s1):
c = request.getfixturevalue(arg[0])
assert c.get(reverse('api_get_recipe_file', args=[ext_recipe_1_s1.pk])).status_code == arg[1]