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 os
import sys from io import BytesIO
from PIL import Image from PIL import Image
from io import BytesIO
def rescale_image_jpeg(image_object, base_width=1020): 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(Unit, 'unit')
self._update_slug_cache(PropertyType, 'property') 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 = [] insert_list = []
update_list = [] update_list = []
update_field_list = [] update_field_list = []
@ -130,8 +124,6 @@ class OpenDataImporter:
insert_list.append({'data': { insert_list.append({'data': {
'name': self.data[datatype][k]['name'], 'name': self.data[datatype][k]['name'],
'plural_name': self.data[datatype][k]['plural_name'] if self.data[datatype][k]['plural_name'] != '' else None, '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']], '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, 'fdc_id': self.data[datatype][k]['fdc_id'] if self.data[datatype][k]['fdc_id'] != '' else None,
'open_data_slug': k, 'open_data_slug': k,
@ -149,8 +141,6 @@ class OpenDataImporter:
id=existing_food_id, id=existing_food_id,
name=self.data[datatype][k]['name'], name=self.data[datatype][k]['name'],
plural_name=self.data[datatype][k]['plural_name'] if self.data[datatype][k]['plural_name'] != '' else None, 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']], 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, fdc_id=self.data[datatype][k]['fdc_id'] if self.data[datatype][k]['fdc_id'] != '' else None,
open_data_slug=k, 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',)) 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 return insert_list + update_list
def import_conversion(self): def import_conversion(self):
@ -197,7 +186,7 @@ class OpenDataImporter:
insert_list = [] insert_list = []
for k in list(self.data[datatype].keys()): 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: try:
insert_list.append(UnitConversion( insert_list.append(UnitConversion(
base_amount=self.data[datatype][k]['base_amount'], 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 import messages
from django.contrib.auth.decorators import user_passes_test from django.contrib.auth.decorators import user_passes_test
from django.core.cache import cache 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.http import HttpResponseRedirect
from django.urls import reverse, reverse_lazy from django.urls import reverse, reverse_lazy
from django.utils.translation import gettext as _ 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 oauth2_provider.models import AccessToken
from rest_framework import permissions from rest_framework import permissions
from rest_framework.permissions import SAFE_METHODS 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): def get_allowed_groups(groups_required):
@ -255,9 +255,6 @@ class CustomIsShared(permissions.BasePermission):
return request.user.is_authenticated return request.user.is_authenticated
def has_object_permission(self, request, view, obj): 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) 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 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) 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): def has_object_permission(self, request, view, obj):
share = request.query_params.get('share', None) share = request.query_params.get('share', None)
@ -332,7 +330,8 @@ class CustomRecipePermission(permissions.BasePermission):
if obj.private: if obj.private:
return ((obj.created_by == request.user) or (request.user in obj.shared.all())) and obj.space == request.space return ((obj.created_by == request.user) or (request.user in obj.shared.all())) and obj.space == request.space
else: 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): class CustomUserPermission(permissions.BasePermission):
@ -361,7 +360,7 @@ class CustomTokenHasScope(TokenHasScope):
""" """
def has_permission(self, request, view): def has_permission(self, request, view):
if type(request.auth) == AccessToken: if isinstance(request.auth, AccessToken):
return super().has_permission(request, view) return super().has_permission(request, view)
else: else:
return request.user.is_authenticated return request.user.is_authenticated
@ -375,7 +374,7 @@ class CustomTokenHasReadWriteScope(TokenHasReadWriteScope):
""" """
def has_permission(self, request, view): def has_permission(self, request, view):
if type(request.auth) == AccessToken: if isinstance(request.auth, AccessToken):
return super().has_permission(request, view) return super().has_permission(request, view)
else: else:
return True return True

View File

@ -14,7 +14,6 @@ from cookbook.models import (CookLog, CustomFilter, Food, Keyword, Recipe, Searc
from recipes import settings 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 # TODO consider creating a simpleListRecipe API that only includes minimum of recipe info and minimal filtering
class RecipeSearch(): class RecipeSearch():
_postgres = settings.DATABASES['default']['ENGINE'] in ['django.db.backends.postgresql_psycopg2', 'django.db.backends.postgresql'] _postgres = settings.DATABASES['default']['ENGINE'] in ['django.db.backends.postgresql_psycopg2', 'django.db.backends.postgresql']
@ -162,7 +161,7 @@ class RecipeSearch():
else: else:
order = [] order = []
# TODO add userpreference for default sort order and replace '-favorite' # 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 # recent and new_recipe are always first; they float a few recipes to the top
if self._num_recent: if self._num_recent:
order += ['-recent'] order += ['-recent']
@ -580,218 +579,3 @@ class RecipeSearch():
.annotate(sibling_onhand=Exists(sibling_onhand_subquery)) .annotate(sibling_onhand=Exists(sibling_onhand_subquery))
.filter(sibling_onhand=True) .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): def parse_keywords(keyword_json, request):
keywords = [] keywords = []
automation_engine = AutomationEngine(request) 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 # keywords as list
for kw in keyword_json: for kw in keyword_json:
@ -425,11 +415,6 @@ def parse_keywords(keyword_json, request):
# if alias exists use that instead # if alias exists use that instead
if len(kw) != 0: if len(kw) != 0:
# if keyword_aliases:
# try:
# kw = keyword_aliases[kw.lower()]
# except KeyError:
# pass
automation_engine.apply_keyword_automation(kw) automation_engine.apply_keyword_automation(kw)
if k := Keyword.objects.filter(name=kw, space=request.space).first(): if k := Keyword.objects.filter(name=kw, space=request.space).first():
keywords.append({'label': str(k), 'name': k.name, 'id': k.id}) keywords.append({'label': str(k), 'name': k.name, 'id': k.id})

View File

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

View File

@ -198,120 +198,3 @@ class RecipeShoppingEditor():
to_delete = self._shopping_list_recipe.entries.exclude(ingredient__in=ingredients) to_delete = self._shopping_list_recipe.entries.exclude(ingredient__in=ingredients)
ShoppingListEntry.objects.filter(id__in=to_delete).delete() ShoppingListEntry.objects.filter(id__in=to_delete).delete()
self._shopping_list_recipe = self.get_shopping_list_recipe(self.id, self.created_by, self.space) 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 import re
from io import BytesIO, StringIO from io import BytesIO, StringIO
from zipfile import ZipFile from zipfile import ZipFile
from PIL import Image from PIL import Image
from cookbook.helper.image_processing import get_filetype from cookbook.helper.image_processing import get_filetype
from cookbook.helper.ingredient_parser import IngredientParser from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.helper.recipe_url_import import iso_duration_to_minutes from cookbook.helper.recipe_url_import import iso_duration_to_minutes
from cookbook.integration.integration import Integration 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): class NextcloudCookbook(Integration):
@ -51,7 +52,6 @@ class NextcloudCookbook(Integration):
ingredients_added = False ingredients_added = False
for s in recipe_json['recipeInstructions']: for s in recipe_json['recipeInstructions']:
instruction_text = ''
if 'text' in s: if 'text' in s:
step = Step.objects.create( step = Step.objects.create(
instruction=s['text'], name=s['name'], space=self.request.space, show_ingredients_table=self.request.user.userpreference.show_step_ingredients, 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 != {}: if nutrition != {}:
recipe.nutrition = NutritionInformation.objects.create(**nutrition, space=self.request.space) recipe.nutrition = NutritionInformation.objects.create(**nutrition, space=self.request.space)
recipe.save() recipe.save()
except Exception as e: except Exception:
pass pass
for f in self.files: for f in self.files:

View File

@ -1,9 +1,11 @@
import json import json
from django.utils.translation import gettext as _
from cookbook.helper.ingredient_parser import IngredientParser from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.integration.integration import Integration from cookbook.integration.integration import Integration
from cookbook.models import Ingredient, Recipe, Step, Keyword, Comment, CookLog from cookbook.models import Comment, CookLog, Ingredient, Keyword, Recipe, Step
from django.utils.translation import gettext as _
class OpenEats(Integration): class OpenEats(Integration):
@ -25,16 +27,16 @@ class OpenEats(Integration):
if file["source"] != '': if file["source"] != '':
instructions += '\n' + _('Recipe source:') + f'[{file["source"]}]({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"] != '': 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: if created:
keyword.move(cuisine_keyword, pos="last-child") keyword.move(cuisine_keyword, pos="last-child")
recipe.keywords.add(keyword) 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"] != '': 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: if created:
keyword.move(course_keyword, pos="last-child") keyword.move(course_keyword, pos="last-child")
recipe.keywords.add(keyword) recipe.keywords.add(keyword)

View File

@ -90,7 +90,7 @@ class Paprika(Integration):
if validators.url(url, public=True): if validators.url(url, public=True):
response = requests.get(url) response = requests.get(url)
self.import_recipe_image(recipe, BytesIO(response.content)) self.import_recipe_image(recipe, BytesIO(response.content))
except: except Exception:
if recipe_json.get("photo_data", None): if recipe_json.get("photo_data", None):
self.import_recipe_image(recipe, BytesIO(base64.b64decode(recipe_json['photo_data'])), filetype='.jpeg') 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 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 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): class PDFexport(Integration):
@ -42,7 +32,6 @@ class PDFexport(Integration):
} }
} }
files = [] files = []
for recipe in recipes: for recipe in recipes:
@ -50,20 +39,18 @@ class PDFexport(Integration):
await page.emulateMedia('print') await page.emulateMedia('print')
await page.setCookie(cookies) await page.setCookie(cookies)
await page.goto('http://'+cmd.default_addr+':'+cmd.default_port+'/view/recipe/'+str(recipe.id), {'waitUntil': 'domcontentloaded'}) await page.goto('http://' + cmd.default_addr + ':' + cmd.default_port + '/view/recipe/' + str(recipe.id), {'waitUntil': 'domcontentloaded'})
await page.waitForSelector('#printReady'); await page.waitForSelector('#printReady')
files.append([recipe.name + '.pdf', await page.pdf(options)]) files.append([recipe.name + '.pdf', await page.pdf(options)])
await page.close(); await page.close()
el.exported_recipes += 1 el.exported_recipes += 1
el.msg += self.get_recipe_processed_msg(recipe) el.msg += self.get_recipe_processed_msg(recipe)
await sync_to_async(el.save, thread_sensitive=True)() await sync_to_async(el.save, thread_sensitive=True)()
await browser.close() await browser.close()
return files return files
def get_files_from_recipes(self, recipes, el, cookie): def get_files_from_recipes(self, recipes, el, cookie):
return asyncio.run(self.get_files_from_recipes_async(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 io import BytesIO
from xml import etree from xml import etree
from lxml import etree
from cookbook.helper.ingredient_parser import IngredientParser 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.integration.integration import Integration
from cookbook.models import Ingredient, Recipe, Step, Keyword from cookbook.models import Ingredient, Keyword, Recipe, Step
class Rezeptsuitede(Integration): class Rezeptsuitede(Integration):
@ -61,14 +59,14 @@ class Rezeptsuitede(Integration):
try: try:
k, created = Keyword.objects.get_or_create(name=recipe_xml.find('head').find('cat').text.strip(), space=self.request.space) k, created = Keyword.objects.get_or_create(name=recipe_xml.find('head').find('cat').text.strip(), space=self.request.space)
recipe.keywords.add(k) recipe.keywords.add(k)
except Exception as e: except Exception:
pass pass
recipe.save() recipe.save()
try: try:
self.import_recipe_image(recipe, BytesIO(base64.b64decode(recipe_xml.find('head').find('picbin').text)), filetype='.jpeg') self.import_recipe_image(recipe, BytesIO(base64.b64decode(recipe_xml.find('head').find('picbin').text)), filetype='.jpeg')
except: except BaseException:
pass pass
return recipe return recipe

View File

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

View File

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

View File

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

View File

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

View File

@ -7,8 +7,6 @@ from django.utils import timezone
from django_scopes import scopes_disabled from django_scopes import scopes_disabled
from oauth2_provider.models import AccessToken from oauth2_provider.models import AccessToken
from cookbook.models import ViewLog
LIST_URL = 'api:accesstoken-list' LIST_URL = 'api:accesstoken-list'
DETAIL_URL = 'api:accesstoken-detail' 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')) register(SupermarketCategoryFactory, 'cat_1', space=LazyFixture('space_1'))
# @pytest.fixture
# def true():
# return True
@pytest.fixture @pytest.fixture
def false(): def false():
return 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 json
import pytest import pytest
@ -15,7 +5,6 @@ from django.contrib import auth
from django.urls import reverse from django.urls import reverse
from django_scopes import scope, scopes_disabled from django_scopes import scope, scopes_disabled
from cookbook.models import Food, ShoppingListEntry
from cookbook.tests.factories import FoodFactory from cookbook.tests.factories import FoodFactory
SHOPPING_LIST_URL = 'api:shoppinglistentry-list' 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) user1 = auth.get_user(u1_s1)
user2 = auth.get_user(u2_s1) user2 = auth.get_user(u2_s1)
food2 = FoodFactory(space=space_1) food2 = FoodFactory(space=space_1)
r = u1_s1.put(reverse(SHOPPING_FOOD_URL, args={food.id})) u1_s1.put(reverse(SHOPPING_FOOD_URL, args={food.id}))
r = u2_s1.put(reverse(SHOPPING_FOOD_URL, args={food2.id})) u2_s1.put(reverse(SHOPPING_FOOD_URL, args={food2.id}))
sl_1 = json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content) sl_1 = json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)
sl_2 = json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content) sl_2 = json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)
assert len(sl_1) == 1 assert len(sl_1) == 1

View File

@ -2,13 +2,10 @@ import json
import pytest import pytest
from django.contrib import auth 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.urls import reverse
from django_scopes import scopes_disabled from django_scopes import scopes_disabled
from cookbook.helper.permission_helper import switch_user_active_space from cookbook.models import InviteLink
from cookbook.models import Ingredient, Step, InviteLink, UserSpace
LIST_URL = 'api:invitelink-list' LIST_URL = 'api:invitelink-list'
DETAIL_URL = 'api:invitelink-detail' DETAIL_URL = 'api:invitelink-detail'

View File

@ -25,6 +25,7 @@ if (Keyword.node_order_by):
else: else:
node_location = 'last-child' node_location = 'last-child'
@pytest.fixture() @pytest.fixture()
def obj_1(space_1): def obj_1(space_1):
return Keyword.objects.get_or_create(name='test_1', space=space_1)[0] 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.urls import reverse
from django_scopes import scope, scopes_disabled 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 from cookbook.tests.factories import RecipeFactory
LIST_URL = 'api:mealplan-list' LIST_URL = 'api:mealplan-list'
@ -149,7 +149,7 @@ def test_add_with_shopping(u1_s1, meal_type):
space = meal_type.space space = meal_type.space
with scope(space=space): with scope(space=space):
recipe = RecipeFactory.create(space=space) recipe = RecipeFactory.create(space=space)
r = u1_s1.post( u1_s1.post(
reverse(LIST_URL), reverse(LIST_URL),
{'recipe': {'id': recipe.id, 'name': recipe.name, 'keywords': []}, 'meal_type': {'id': meal_type.id, 'name': meal_type.name}, {'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}, '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.urls import reverse
from django_scopes import scopes_disabled from django_scopes import scopes_disabled
from cookbook.models import Food, MealType from cookbook.models import MealType
LIST_URL = 'api:mealtype-list' LIST_URL = 'api:mealtype-list'
DETAIL_URL = 'api:mealtype-detail' DETAIL_URL = 'api:mealtype-detail'

View File

@ -1,11 +1,10 @@
import json import json
import pytest import pytest
from django.contrib import auth
from django.urls import reverse from django.urls import reverse
from django_scopes import scopes_disabled 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' LIST_URL = 'api:property-list'
DETAIL_URL = 'api:property-detail' DETAIL_URL = 'api:property-detail'

View File

@ -1,11 +1,10 @@
import json import json
import pytest import pytest
from django.contrib import auth
from django.urls import reverse from django.urls import reverse
from django_scopes import scopes_disabled from django_scopes import scopes_disabled
from cookbook.models import Food, MealType, PropertyType from cookbook.models import MealType, PropertyType
LIST_URL = 'api:propertytype-list' LIST_URL = 'api:propertytype-list'
DETAIL_URL = 'api:propertytype-detail' 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() 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 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_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.created_by = auth.get_user(u1_s1)
recipe_1_s1.private = True recipe_1_s1.private = True
@ -100,7 +101,6 @@ def test_update(arg, request, recipe_1_s1):
j, j,
content_type='application/json' content_type='application/json'
) )
response = json.loads(r.content)
assert r.status_code == arg[1] assert r.status_code == arg[1]
if r.status_code == 200: if r.status_code == 200:
validate_recipe(j, json.loads(r.content)) 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 assert r.status_code == 200
response = json.loads(r.content) response = json.loads(r.content)
assert len(response) == 2 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) response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?limit=1').content)
assert len(response) == 1 assert len(response) == 1

View File

@ -1,11 +1,9 @@
import json import json
import factory
import pytest import pytest
from django.contrib import auth from django.contrib import auth
from django.urls import reverse from django.urls import reverse
from django_scopes import scopes_disabled from django_scopes import scopes_disabled
from pytest_factoryboy import LazyFixture, register
from cookbook.tests.factories import RecipeFactory 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 params = request.param # request.param is a magic variable
except AttributeError: except AttributeError:
params = {} 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__recipe_count = params.get('steps__recipe_count', 0)
steps__food_recipe_count = params.get('steps__food_recipe_count', {}) steps__food_recipe_count = params.get('steps__food_recipe_count', {})
created_by = params.get('created_by', auth.get_user(u1_s1)) 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( return RecipeFactory.create(
steps__recipe_count=steps__recipe_count, steps__recipe_count=steps__recipe_count,
steps__food_recipe_count=steps__food_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, created_by=created_by,
space=space_1, 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}}), # 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 ({'steps__food_recipe_count': {'step': 0, 'count': 1}, 'steps__recipe_count': 1}), # shopping list from recipe with StepRecipe and food recipe
], indirect=['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(): with scopes_disabled():
recipe.space = space_2 recipe.space = space_2
recipe.save() recipe.save()

View File

@ -5,7 +5,7 @@ from django.contrib import auth
from django.urls import reverse from django.urls import reverse
from django_scopes import scopes_disabled 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' LIST_URL = 'api:shoppinglist-list'
DETAIL_URL = 'api:shoppinglist-detail' DETAIL_URL = 'api:shoppinglist-detail'

View File

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

View File

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

View File

@ -2,11 +2,10 @@ import json
import pytest import pytest
from django.contrib import auth from django.contrib import auth
from django.forms import model_to_dict
from django.urls import reverse from django.urls import reverse
from django_scopes import scopes_disabled 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' LIST_URL = 'api:shoppinglistrecipe-list'
DETAIL_URL = 'api:shoppinglistrecipe-detail' DETAIL_URL = 'api:shoppinglistrecipe-detail'
@ -21,7 +20,7 @@ def obj_1(space_1, u1_s1, recipe_1_s1):
@pytest.fixture @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) 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 = ShoppingList.objects.create(created_by=auth.get_user(u1_s1), space=space_1, )
s.recipes.add(r) 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']) @pytest.mark.parametrize("recipe", [{'steps__ingredients__header': 1}], indirect=['recipe'])
def test_shopping_with_header_ingredient(u1_s1, 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})) 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(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)) == 10
assert len(json.loads( assert len(json.loads(

View File

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

View File

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

View File

@ -1,11 +1,10 @@
import json import json
import pytest import pytest
from django.contrib import auth
from django.urls import reverse from django.urls import reverse
from django_scopes import scopes_disabled from django_scopes import scopes_disabled
from cookbook.models import RecipeBook, Supermarket from cookbook.models import Supermarket
LIST_URL = 'api:supermarket-list' LIST_URL = 'api:supermarket-list'
DETAIL_URL = 'api:supermarket-detail' DETAIL_URL = 'api:supermarket-detail'
@ -48,7 +47,6 @@ def test_list_filter(obj_1, obj_2, u1_s1):
assert r.status_code == 200 assert r.status_code == 200
response = json.loads(r.content) response = json.loads(r.content)
assert len(response) == 2 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) response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?limit=1').content)
assert len(response) == 1 assert len(response) == 1

View File

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

View File

@ -5,7 +5,7 @@ from django.contrib import auth
from django.urls import reverse from django.urls import reverse
from django_scopes import scopes_disabled 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 from cookbook.tests.conftest import get_random_food, get_random_unit
LIST_URL = 'api:unitconversion-list' LIST_URL = 'api:unitconversion-list'

View File

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

View File

@ -120,7 +120,6 @@ def test_default_inherit_fields(u1_s1, u1_s2, space_1, space_2):
r = u1_s1.get( r = u1_s1.get(
reverse(DETAIL_URL, args={auth.get_user(u1_s1).id}), 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 # inherit all possible fields
with scope(space=space_1): with scope(space=space_1):

View File

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

View File

@ -36,18 +36,6 @@ def enable_db_access_for_all_tests(db):
pass 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 --------------------- # ---------------------- OBJECT FIXTURES ---------------------
def get_random_recipe(space_1, u1_s1): 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 # file and url are metadata not related to the recipe
[expected.pop(k) for k in ['file', 'url'] if k in expected] [expected.pop(k) for k in ['file', 'url'] if k in expected]
# if a key is a list remove it to deal with later # 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: for k in lists:
expected_lists[k] = expected.pop(k) expected_lists[k] = expected.pop(k)
target_lists[k] = recipe.pop(k) target_lists[k] = recipe.pop(k)
@ -157,7 +145,7 @@ def dict_compare(d1, d2, details=False):
d1_keys = set(d1.keys()) d1_keys = set(d1.keys())
d2_keys = set(d2.keys()) d2_keys = set(d2.keys())
shared = d1_keys.intersection(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) not_dicts = shared - set(sub_dicts)
added = d1_keys - d2_keys added = d1_keys - d2_keys
removed = d2_keys - d1_keys removed = d2_keys - d1_keys

View File

@ -1,4 +1,5 @@
import inspect
from datetime import date from datetime import date
from decimal import Decimal from decimal import Decimal
@ -11,12 +12,6 @@ from pytest_factoryboy import register
from cookbook.models import UserSpace 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() faker = FakerFactory.create()
@ -96,7 +91,6 @@ class SupermarketCategoryFactory(factory.django.DjangoModelFactory):
django_get_or_create = ('name', 'space',) django_get_or_create = ('name', 'space',)
# @factory.django.mute_signals(post_save)
@register @register
class FoodFactory(factory.django.DjangoModelFactory): class FoodFactory(factory.django.DjangoModelFactory):
"""Food factory.""" """Food factory."""
@ -451,17 +445,6 @@ class RecipeFactory(factory.django.DjangoModelFactory):
for step in extracted: for step in extracted:
self.steps.add(step) 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: class Meta:
model = 'cookbook.Recipe' 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", "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", "source_url": "https://www.thespruceeats.com/creamy-potato-soup-with-ham-3059797",
"keywords": [ "keywords": [
{
"label": "soup",
"name": "soup",
"id": 18,
},
{ {
"label": "lunch", "label": "soup",
"name": "lunch", "name": "soup",
}, "id": 18,
},
{ {
"label": "entree", "label": "lunch",
"name": "entree", "name": "lunch",
}, },
{ {
"label": "side dish", "label": "entree",
"name": "side dish", "name": "entree",
"id": 14, },
},
{ {
"label": "www.thespruceeats.com", "label": "side dish",
"name": "www.thespruceeats.com", "name": "side dish",
}, "id": 14,
},
{ {
"label": "southern", "label": "www.thespruceeats.com",
"name": "southern", "name": "www.thespruceeats.com",
"id": 27, },
},
{ {
"label": "cheddar", "label": "southern",
"name": "cheddar", "name": "southern",
}, "id": 27,
},
{ {
"label": "dinner", "label": "cheddar",
"name": "dinner", "name": "cheddar",
} },
{
"label": "dinner",
"name": "dinner",
}
], ],
"steps": [ "steps": [
{ {

View File

@ -1,11 +1,12 @@
from decimal import Decimal
from django.contrib import auth from django.contrib import auth
from django.core.cache import caches from django.core.cache import caches
from django_scopes import scopes_disabled from django_scopes import scopes_disabled
from decimal import Decimal
from cookbook.helper.cache_helper import CacheHelper from cookbook.helper.cache_helper import CacheHelper
from cookbook.helper.property_helper import FoodPropertyHelper 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): 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) property_values = FoodPropertyHelper(space_1).calculate_recipe_properties(recipe_2)
assert property_fat.id not in property_values assert property_fat.id not in property_values

View File

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

View File

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

View File

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