diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a113ead1..1aa68a27 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,14 +9,14 @@ jobs: strategy: max-parallel: 4 matrix: - python-version: [3.8] + python-version: [3.9] steps: - uses: actions/checkout@v1 - - name: Set up Python 3.8 + - name: Set up Python 3.9 uses: actions/setup-python@v1 with: - python-version: 3.8 + python-version: 3.9 - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/.idea/recipes.iml b/.idea/recipes.iml index e1dd7064..6d3000d1 100644 --- a/.idea/recipes.iml +++ b/.idea/recipes.iml @@ -18,7 +18,7 @@ - + diff --git a/cookbook/helper/recipe_url_import.py b/cookbook/helper/recipe_url_import.py index ec02eb32..50813775 100644 --- a/cookbook/helper/recipe_url_import.py +++ b/cookbook/helper/recipe_url_import.py @@ -2,6 +2,7 @@ import random import re from isodate import parse_duration as iso_parse_duration from isodate.isoerror import ISO8601Error +from recipe_scrapers._exceptions import ElementNotFoundInHtml from cookbook.helper.ingredient_parser import parse as parse_single_ingredient from cookbook.models import Keyword @@ -17,12 +18,12 @@ def get_from_scraper(scrape, space): recipe_json = {} try: recipe_json['name'] = parse_name(scrape.title() or scrape.schema.data.get('name') or '') - except (TypeError, AttributeError): + except (TypeError, AttributeError,ElementNotFoundInHtml): recipe_json['name'] = '' try: description = scrape.schema.data.get("description") or '' - except AttributeError: + except (AttributeError,ElementNotFoundInHtml): description = '' recipe_json['description'] = parse_description(description) @@ -30,21 +31,27 @@ def get_from_scraper(scrape, space): try: servings = scrape.yields() servings = int(re.findall(r'\b\d+\b', servings)[0]) - except (AttributeError, ValueError, IndexError): + except (AttributeError,ElementNotFoundInHtml, ValueError, IndexError): servings = 1 recipe_json['servings'] = servings - recipe_json['prepTime'] = get_minutes(scrape.schema.data.get("prepTime")) or 0 - recipe_json['cookTime'] = get_minutes(scrape.schema.data.get("cookTime")) or 0 + try: + recipe_json['prepTime'] = get_minutes(scrape.schema.data.get("prepTime")) or 0 + except (AttributeError, ElementNotFoundInHtml): + recipe_json['prepTime'] = 0 + try: + recipe_json['cookTime'] = get_minutes(scrape.schema.data.get("cookTime")) or 0 + except (AttributeError, ElementNotFoundInHtml): + recipe_json['cookTime'] = 0 if recipe_json['cookTime'] + recipe_json['prepTime'] == 0: try: recipe_json['prepTime'] = get_minutes(scrape.total_time()) or 0 - except AttributeError: + except (AttributeError,ElementNotFoundInHtml): pass try: recipe_json['image'] = parse_image(scrape.image()) or '' - except (AttributeError, TypeError, SchemaOrgException): + except (AttributeError,ElementNotFoundInHtml, TypeError, SchemaOrgException): recipe_json['image'] = '' keywords = [] @@ -56,7 +63,7 @@ def get_from_scraper(scrape, space): if scrape.schema.data.get('recipeCuisine'): keywords += listify_keywords(scrape.schema.data.get("recipeCuisine")) recipe_json['keywords'] = parse_keywords(list(set(map(str.casefold, keywords))), space) - except AttributeError: + except (AttributeError,ElementNotFoundInHtml): recipe_json['keywords'] = keywords try: @@ -97,12 +104,12 @@ def get_from_scraper(scrape, space): } ) recipe_json['recipeIngredient'] = ingredients - except AttributeError: + except (AttributeError,ElementNotFoundInHtml): recipe_json['recipeIngredient'] = ingredients try: recipe_json['recipeInstructions'] = parse_instructions(scrape.instructions()) - except AttributeError: + except (AttributeError,ElementNotFoundInHtml): recipe_json['recipeInstructions'] = "" if scrape.url: diff --git a/cookbook/templates/url_import.html b/cookbook/templates/url_import.html index d90b604f..d70104c0 100644 --- a/cookbook/templates/url_import.html +++ b/cookbook/templates/url_import.html @@ -83,6 +83,25 @@ + + + + + + + @@ -274,18 +293,18 @@
- -
-
+
+

{% trans 'Discovered Attributes' %}

- {% trans 'Drag recipe attributes from below into the appropriate box on the left. Click any node to display its full properties.' %} + {% trans 'Drag recipe attributes from below into the appropriate box on the left. Click any node to display its full properties.' %}
@@ -299,8 +318,8 @@ images
-
@@ -312,9 +331,9 @@
{% trans 'Items dragged to Blank Field will be appended.'%}
-
@@ -332,7 +351,7 @@
-
@@ -343,17 +362,17 @@
- +
    -
    - [[txt]] + style="display:flex; justify-content:space-between;"> + [[txt]]
@@ -361,10 +380,10 @@
    -
    + style="display:flex; justify-content:space-between;"> Image
    diff --git a/cookbook/views/api.py b/cookbook/views/api.py index 08b7c090..248f8116 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -16,10 +16,6 @@ from django.http import FileResponse, HttpResponse, JsonResponse from django.shortcuts import redirect, get_object_or_404 from django.utils.translation import gettext as _ from icalendar import Calendar, Event - -from rest_framework import decorators, viewsets -from rest_framework.exceptions import APIException, PermissionDenied - from recipe_scrapers import scrape_me, WebsiteNotImplementedError, NoSchemaFoundInWildMode from rest_framework import decorators, viewsets from rest_framework.exceptions import APIException, PermissionDenied @@ -34,13 +30,11 @@ from cookbook.helper.ingredient_parser import parse from cookbook.helper.permission_helper import (CustomIsAdmin, CustomIsGuest, CustomIsOwner, CustomIsShare, CustomIsShared, CustomIsUser, - - group_required, share_link_valid) + group_required) from cookbook.helper.recipe_html_import import get_recipe_from_source -from cookbook.helper.recipe_url_import import get_from_scraper -from cookbook.helper.recipe_search import search_recipes -from cookbook.helper.recipe_url_import import get_from_html, get_from_scraper, find_recipe_json +from cookbook.helper.recipe_search import search_recipes +from cookbook.helper.recipe_url_import import get_from_scraper from cookbook.models import (CookLog, Food, Ingredient, Keyword, MealPlan, MealType, Recipe, RecipeBook, ShoppingList, ShoppingListEntry, ShoppingListRecipe, Step, diff --git a/docs/install/manual.md b/docs/install/manual.md index 7e5b0fcd..7ebd3cf1 100644 --- a/docs/install/manual.md +++ b/docs/install/manual.md @@ -3,7 +3,7 @@ These intructions are inspired from a standard django/gunicorn/postgresql instructions ([for example](https://www.digitalocean.com/community/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu-16-04)) !!! warning - Be sure to use pyton3.8 and pip related to python 3.8. Depending on your distribution calling `python` or `pip` will use python2 instead of pyton 3.8. + Be sure to use pyton3.9 and pip related to python 3.9. Depending on your distribution calling `python` or `pip` will use python2 instead of pyton 3.9. ## Prerequisites @@ -12,7 +12,7 @@ These intructions are inspired from a standard django/gunicorn/postgresql instru Get the last version from the repository: `git clone https://github.com/vabene1111/recipes.git -b master` Install postgresql requirements: `sudo apt install libpq-dev postgresql` -Install project requirements: `pip3.8 install -r requirements.txt` +Install project requirements: `pip3.9 install -r requirements.txt` ## Setup postgresql @@ -44,11 +44,11 @@ wget https://raw.githubusercontent.com/vabene1111/recipes/develop/.env.template Execute `export $(cat .env |grep "^[^#]" | xargs)` to load variables from `.env` -Execute `/python3.8 manage.py migrate` +Execute `/python3.9 manage.py migrate` and revert superuser from postgres: `sudo -u postgres psql` and `ALTER USER djangouser WITH NOSUPERUSER;` -Generate static files: `python3.8 manage.py collectstatic` and remember the folder where files have been copied. +Generate static files: `python3.9 manage.py collectstatic` and remember the folder where files have been copied. ## Setup web services @@ -70,7 +70,7 @@ RestartSec=3 Group=www-data WorkingDirectory=/media/data/recipes EnvironmentFile=/media/data/recipes/.env -ExecStart=/opt/.pyenv/versions/3.8.5/bin/gunicorn --error-logfile /tmp/gunicorn_err.log --log-level debug --capture-output --bind unix:/media/data/recipes/recipes.sock recipes.wsgi:application +ExecStart=/opt/.pyenv/versions/3.9/bin/gunicorn --error-logfile /tmp/gunicorn_err.log --log-level debug --capture-output --bind unix:/media/data/recipes/recipes.sock recipes.wsgi:application [Install] WantedBy=multi-user.target diff --git a/docs/install/other.md b/docs/install/other.md index 1221b209..4b42eb09 100644 --- a/docs/install/other.md +++ b/docs/install/other.md @@ -1,7 +1,7 @@ !!! info "Community Contributed" The examples in this section were contributed by members of the community. This page especially contains some setups that might help you if you really want to go down a certain path but none - of the examples are supported (as i simply am not able to give you support for them). + of the examples are supported (as I simply am not able to give you support for them). ## Apache + Traefik + Sub-Path diff --git a/requirements.txt b/requirements.txt index b5deb30a..b2361280 100644 --- a/requirements.txt +++ b/requirements.txt @@ -31,7 +31,7 @@ Jinja2==2.11.3 django-webpack-loader==0.7.0 django-js-reverse==0.9.1 django-allauth==0.44.0 -recipe-scrapers==13.1.1 +recipe-scrapers==13.2.1 django-scopes==1.2.0 pytest==6.2.3 pytest-django==4.2.0