Skip to content

Commit

Permalink
Merge branch 'main' into maintenance/add-preliminary-py313-support
Browse files Browse the repository at this point in the history
  • Loading branch information
jayaddison authored Oct 3, 2024
2 parents cd2de60 + d3e6bd8 commit bf0a49f
Show file tree
Hide file tree
Showing 26 changed files with 8,396 additions and 40 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/coverage.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "< 3.12" # ref: https://github.com/hhursev/recipe-scrapers/issues/909
python-version: "3.x"
- name: run unittests
run: |
pip install tox
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/unittests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-13, windows-latest]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13.0-rc.3"]
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13.0-rc.3"]
include:
# set toxenv to workaround-darwin on macos (check tox.ini)
- toxenv: py
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ repos:
rev: v3.15.1
hooks:
- id: pyupgrade
args: [--py38-plus]
args: [--py39-plus]
- repo: https://github.com/sphinx-contrib/sphinx-lint
rev: v0.9.1
hooks:
Expand Down
5 changes: 4 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ Scrapers available for:
- `https://franzoesischkochen.de/ <https://franzoesischkochen.de/>`_
- `https://www.gesund-aktiv.com/ <https://www.gesund-aktiv.com>`_
- `https://gimmesomeoven.com/ <https://www.gimmesomeoven.com/>`_
- `https://glutenfreeonashoestring.com/ <https://glutenfreeonashoestring.com/>`_
- `https://godt.no/ <https://godt.no/>`_
- `https://gonnawantseconds.com/ <https://gonnawantseconds.com>`_
- `https://goodfooddiscoveries.com/ <https://goodfooddiscoveries.com/>`_
Expand Down Expand Up @@ -394,10 +395,12 @@ Scrapers available for:
- `https://www.thecookierookie.com/ <https://www.thecookierookie.com/>`_
- `https://thecookingguy.com/ <https://thecookingguy.com>`_
- `https://theexpertguides.com/ <https://theexpertguides.com>`_
- `https://theglutenfreeaustrian.com/ <https://theglutenfreeaustrian.com/>`_
- `https://thehappyfoodie.co.uk/ <https://thehappyfoodie.co.uk>`_
- `https://thekitchencommunity.org/ <https://thekitchencommunity.org/>`_
- `https://www.thekitchenmagpie.com/ <https://www.thekitchenmagpie.com>`_
- `https://thekitchn.com/ <https://thekitchn.com/>`_
- `https://theloopywhisk.com/ <https://theloopywhisk.com/>`_
- `https://www.themagicalslowcooker.com/ <https://www.themagicalslowcooker.com/>`_
- `https://themodernproper.com/ <https://themodernproper.com/>`_
- `https://www.thepalatablelife.com <https://www.thepalatablelife.com/>`_
Expand Down Expand Up @@ -474,7 +477,7 @@ If you want a scraper for a new site added
For Devs / Contribute
---------------------

Assuming you have ``>=python3.8`` installed, navigate to the directory where you want this project to live in and drop these lines
Assuming you have ``>=python3.9`` installed, navigate to the directory where you want this project to live in and drop these lines

.. code:: shell
Expand Down
3 changes: 1 addition & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ license = {text = "MIT License"}
classifiers = [
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
Expand All @@ -26,7 +25,7 @@ classifiers = [
"Topic :: Software Development :: Libraries",
]
dynamic = ["version", "readme"]
requires-python = ">= 3.8"
requires-python = ">= 3.9"
dependencies = [
"beautifulsoup4 >= 4.12.3",
"extruct >= 0.17.0",
Expand Down
6 changes: 6 additions & 0 deletions recipe_scrapers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@
from .giallozafferano import GialloZafferano
from .gimmesomeoven import GimmeSomeOven
from .globo import Globo
from .glutenfreeonashoestring import GlutenFreeOnAShoeString
from .godt import Godt
from .gonnawantseconds import GonnaWantSeconds
from .goodfooddiscoveries import GoodFoodDiscoveries
Expand Down Expand Up @@ -343,10 +344,12 @@
from .thecookierookie import TheCookieRookie
from .thecookingguy import TheCookingGuy
from .theexpertguides import TheExpertGuides
from .theglutenfreeaustrian import TheGlutenFreeAustrian
from .thehappyfoodie import TheHappyFoodie
from .thekitchencommunity import TheKitchenCommunity
from .thekitchenmagpie import TheKitchenMagPie
from .thekitchn import TheKitchn
from .theloopywhisk import TheLoopyWhisk
from .themagicalslowcooker import TheMagicalSlowCooker
from .themodernproper import TheModernProper
from .thepalatablelife import ThePalatableLife
Expand Down Expand Up @@ -480,6 +483,7 @@
FamilyfoodOnTheTable.host(): FamilyfoodOnTheTable,
FifteenGram.host(): FifteenGram,
FitSlowCookerQueen.host(): FitSlowCookerQueen,
GlutenFreeOnAShoeString.host(): GlutenFreeOnAShoeString,
GourmetTraveller.host(): GourmetTraveller,
GrandFrais.host(): GrandFrais,
HeatherChristo.host(): HeatherChristo,
Expand Down Expand Up @@ -521,6 +525,8 @@
TasteAtlas.host(): TasteAtlas,
TheCookieRookie.host(): TheCookieRookie,
TheCookingGuy.host(): TheCookingGuy,
TheGlutenFreeAustrian.host(): TheGlutenFreeAustrian,
TheLoopyWhisk.host(): TheLoopyWhisk,
ThePalatableLife.host(): ThePalatableLife,
TheSaltyMarshmallow.host(): TheSaltyMarshmallow,
Thinlicious.host(): Thinlicious,
Expand Down
5 changes: 2 additions & 3 deletions recipe_scrapers/_abstract.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import inspect
from collections import OrderedDict
from typing import List
from urllib.parse import urljoin

from bs4 import BeautifulSoup
Expand Down Expand Up @@ -98,15 +97,15 @@ def ingredients(self):
"""Ingredients of the recipe."""
raise NotImplementedError("This should be implemented.")

def ingredient_groups(self) -> List[IngredientGroup]:
def ingredient_groups(self) -> list[IngredientGroup]:
"""List of ingredient groups."""
return [IngredientGroup(purpose=None, ingredients=self.ingredients())]

def instructions(self) -> str:
"""Instructions to prepare the recipe."""
raise NotImplementedError("This should be implemented.")

def instructions_list(self) -> List[str]:
def instructions_list(self) -> list[str]:
"""Instructions to prepare the recipe as a list."""
return [
instruction
Expand Down
21 changes: 11 additions & 10 deletions recipe_scrapers/_grouping_utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

from collections import defaultdict
from dataclasses import dataclass
from typing import Dict, List, Optional

from bs4 import BeautifulSoup

Expand All @@ -9,8 +10,8 @@

@dataclass
class IngredientGroup:
ingredients: List[str]
purpose: Optional[str] = (
ingredients: list[str]
purpose: str | None = (
None # this group of ingredients is {purpose} (e.g. "For the dressing")
)

Expand Down Expand Up @@ -50,7 +51,7 @@ def score_sentence_similarity(first: str, second: str) -> float:
return 2 * intersection / (len(first_bigrams) + len(second_bigrams))


def best_match(test_string: str, target_strings: List[str]) -> str:
def best_match(test_string: str, target_strings: list[str]) -> str:
"""Find the best match for a given test string within a list of target strings.
This function utilizes the score_sentence_similarity function to compare the test string
Expand All @@ -61,7 +62,7 @@ def best_match(test_string: str, target_strings: List[str]) -> str:
----------
test_string : str
The string to find the best match for.
target_strings : List[str]
target_strings : list[str]
A list of strings to compare against the test string.
Returns
Expand All @@ -78,11 +79,11 @@ def best_match(test_string: str, target_strings: List[str]) -> str:


def group_ingredients(
ingredients_list: List[str],
ingredients_list: list[str],
soup: BeautifulSoup,
group_heading: str,
group_element: str,
) -> List[IngredientGroup]:
) -> list[IngredientGroup]:
"""
Group ingredients into sublists according to the heading in the recipe.
Expand All @@ -93,7 +94,7 @@ def group_ingredients(
Parameters
----------
ingredients_list : List[str]
ingredients_list : list[str]
Ingredients extracted by the scraper.
soup : BeautifulSoup
Parsed HTML of the recipe page.
Expand All @@ -104,7 +105,7 @@ def group_ingredients(
Returns
-------
List[IngredientGroup]
list[IngredientGroup]
groupings of ingredients categorized by their purpose or heading.
Raises
Expand All @@ -119,7 +120,7 @@ def group_ingredients(
f"Found {len(found_ingredients)} grouped ingredients but was expecting to find {len(ingredients_list)}."
)

groupings: Dict[Optional[str], List[str]] = defaultdict(list)
groupings: dict[str | None, list[str]] = defaultdict(list)
current_heading = None

elements = soup.select(f"{group_heading}, {group_element}")
Expand Down
16 changes: 16 additions & 0 deletions recipe_scrapers/glutenfreeonashoestring.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from ._abstract import AbstractScraper
from ._utils import get_equipment


class GlutenFreeOnAShoeString(AbstractScraper):
@classmethod
def host(cls):
return "glutenfreeonashoestring.com"

def equipment(self):
equipment_items = [
equip.get_text()
for equip in self.soup.find_all("div", class_="wprm-recipe-equipment-name")
if equip.get_text()
]
return get_equipment(equipment_items)
7 changes: 3 additions & 4 deletions recipe_scrapers/kitchenaidaustralia.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import re
from typing import List

from ._abstract import AbstractScraper
from ._grouping_utils import IngredientGroup
Expand Down Expand Up @@ -36,7 +35,7 @@ def ingredients(self):
elements = self._parse_list(ingredients)
return elements

def ingredient_groups(self) -> List[IngredientGroup]:
def ingredient_groups(self) -> list[IngredientGroup]:
recipe = self._get_recipe()
ingredients = recipe.find("div", {"class": "leftPanel"})

Expand All @@ -54,7 +53,7 @@ def ingredient_groups(self) -> List[IngredientGroup]:
def instructions(self):
return "\n".join(self.instructions_list())

def instructions_list(self) -> List[str]:
def instructions_list(self) -> list[str]:
recipe = self._get_recipe()
method = recipe.find("div", {"class": "rightPanel"})

Expand Down Expand Up @@ -87,7 +86,7 @@ def _parse_summary_item(self, item):
"""
return item.find_next_sibling("p").text

def _parse_list(self, container) -> List[str]:
def _parse_list(self, container) -> list[str]:
"""
Get the text from each of the li elements contained by the given container.
"""
Expand Down
6 changes: 2 additions & 4 deletions recipe_scrapers/nihhealthyeating.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from typing import List

from ._abstract import AbstractScraper
from ._exceptions import ElementNotFoundInHtml, StaticValueException
from ._grouping_utils import IngredientGroup
Expand Down Expand Up @@ -69,7 +67,7 @@ def image(self):

return image_relative_url

def ingredient_groups(self) -> List[IngredientGroup]:
def ingredient_groups(self) -> list[IngredientGroup]:
# This content must be present for recipes on this website.
ingredients_div = self.soup.find("div", {"id": "ingredients"})
section = []
Expand Down Expand Up @@ -123,7 +121,7 @@ def ingredient_groups(self) -> List[IngredientGroup]:

return [IngredientGroup(ingredients_list)]

def ingredients(self) -> List[str]:
def ingredients(self) -> list[str]:
results = []
for ingredient_group in self.ingredient_groups():
results.extend(ingredient_group.ingredients)
Expand Down
2 changes: 1 addition & 1 deletion recipe_scrapers/plugins/_interface.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from abc import ABC, abstractmethod
from typing import Iterable
from collections.abc import Iterable


class PluginInterface(ABC):
Expand Down
4 changes: 1 addition & 3 deletions recipe_scrapers/streetkitchen.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from typing import List

from ._abstract import AbstractScraper
from ._grouping_utils import IngredientGroup, group_ingredients
from ._utils import get_minutes, get_yields, normalize_string
Expand Down Expand Up @@ -61,7 +59,7 @@ def author(self):
self.soup.find("a", {"rel": "author"}).find("img")["alt"]
)

def ingredient_groups(self) -> List[IngredientGroup]:
def ingredient_groups(self) -> list[IngredientGroup]:
return group_ingredients(
self.ingredients(),
self.soup,
Expand Down
29 changes: 29 additions & 0 deletions recipe_scrapers/theglutenfreeaustrian.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from ._abstract import AbstractScraper
from ._grouping_utils import group_ingredients
from ._utils import get_yields


class TheGlutenFreeAustrian(AbstractScraper):
@classmethod
def host(cls):
return "theglutenfreeaustrian.com"

def ingredient_groups(self):
ingredient_groups = group_ingredients(
self.ingredients(),
self.soup,
".mv-create-ingredients h4",
".mv-create-ingredients ul li",
)

schema_title = self.schema.title()

for group in ingredient_groups:
if group.purpose == schema_title:
group.purpose = None

return ingredient_groups

def yields(self):
yield_element = self.soup.select_one(".mv-create-title-wrap .mv-create-yield")
return get_yields(yield_element)
16 changes: 16 additions & 0 deletions recipe_scrapers/theloopywhisk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from ._abstract import AbstractScraper
from ._grouping_utils import group_ingredients


class TheLoopyWhisk(AbstractScraper):
@classmethod
def host(cls):
return "theloopywhisk.com"

def ingredient_groups(self):
return group_ingredients(
self.ingredients(),
self.soup,
".wprm-recipe-ingredient-group h4",
".wprm-recipe-ingredient",
)
Loading

0 comments on commit bf0a49f

Please sign in to comment.