remove unused imports, variables and commented code
from tests
This commit is contained in:
parent
78b1386a1c
commit
1f0cd58d7d
@ -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):
|
||||
|
@ -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'],
|
||||
|
@ -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
|
||||
|
@ -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())
|
||||
|
@ -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})
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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')
|
||||
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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 = []
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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'
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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'
|
||||
|
@ -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]
|
||||
|
@ -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},
|
||||
|
@ -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'
|
||||
|
@ -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'
|
||||
|
@ -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'
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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'
|
||||
|
@ -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
|
||||
|
||||
|
@ -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):
|
||||
|
@ -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)
|
||||
|
@ -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(
|
||||
|
@ -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'
|
||||
|
||||
|
@ -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'
|
||||
|
@ -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
|
||||
|
@ -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'
|
||||
|
@ -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'
|
||||
|
@ -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(
|
||||
|
@ -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):
|
||||
|
@ -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'
|
||||
|
||||
|
@ -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
|
||||
|
@ -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'
|
||||
|
||||
|
@ -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": [
|
||||
{
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
|
@ -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]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user