add NEVER_UNIT automation

This commit is contained in:
smilerz
2023-04-24 10:59:48 -05:00
parent 5d5eb45b5a
commit 8fa00972bd
6 changed files with 178 additions and 82 deletions

View File

@@ -4,7 +4,7 @@ import unicodedata
from django.core.cache import caches
from cookbook.models import Unit, Food, Automation, Ingredient
from cookbook.models import Automation, Food, Ingredient, Unit
class IngredientParser:
@@ -12,6 +12,7 @@ class IngredientParser:
ignore_rules = False
food_aliases = {}
unit_aliases = {}
never_unit = {}
def __init__(self, request, cache_mode, ignore_automations=False):
"""
@@ -40,9 +41,19 @@ class IngredientParser:
for a in Automation.objects.filter(space=self.request.space, disabled=False, type=Automation.UNIT_ALIAS).only('param_1', 'param_2').order_by('order').all():
self.unit_aliases[a.param_1] = a.param_2
caches['default'].set(UNIT_CACHE_KEY, self.unit_aliases, 30)
NEVER_UNIT_CACHE_KEY = f'automation_never_unit_{self.request.space.pk}'
if c := caches['default'].get(NEVER_UNIT_CACHE_KEY, None):
self.never_unit = c
caches['default'].touch(NEVER_UNIT_CACHE_KEY, 30)
else:
for a in Automation.objects.filter(space=self.request.space, disabled=False, type=Automation.NEVER_UNIT).only('param_1', 'param_2').order_by('order').all():
self.never_unit[a.param_1] = a.param_2
caches['default'].set(NEVER_UNIT_CACHE_KEY, self.never_unit, 30)
else:
self.food_aliases = {}
self.unit_aliases = {}
self.never_unit = {}
def apply_food_automation(self, food):
"""
@@ -205,6 +216,49 @@ class IngredientParser:
food, note = self.parse_food_with_comma(tokens)
return food, note
def apply_never_unit_automations(self, tokens):
"""
Moves a string that should never be treated as a unit to next token and optionally replaced with default unit
e.g. NEVER_UNIT: param1: egg, param2: None would modify ['1', 'egg', 'white'] to ['1', '', 'egg', 'white']
or NEVER_UNIT: param1: egg, param2: pcs would modify ['1', 'egg', 'yolk'] to ['1', 'pcs', 'egg', 'yolk']
:param1 string: string that should never be considered a unit, will be moved to token[2]
:param2 (optional) unit as string: will insert unit string into token[1]
:return: unit as string (possibly changed by automation)
"""
if self.ignore_rules:
return tokens
new_unit = None
alt_unit = self.apply_unit_automation(tokens[1])
never_unit = False
if self.never_unit:
try:
new_unit = self.never_unit[tokens[1]]
never_unit = True
except KeyError:
return tokens
else:
if automation := Automation.objects.filter(space=self.request.space, type=Automation.UNIT_ALIAS, param_1__in=[tokens[1], alt_unit], disabled=False).order_by('order').first():
new_unit = automation.param_2
never_unit = True
if never_unit:
tokens.insert(1, new_unit)
return tokens
def parse_tokens(self, tokens):
"""
parser that applies automations to unmodified tokens
"""
if self.ignore_rules:
return tokens
return self.apply_never_unit_automations(tokens)
def parse(self, ingredient):
"""
Main parsing function, takes an ingredient string (e.g. '1 l Water') and extracts amount, unit, food, ...
@@ -257,6 +311,7 @@ class IngredientParser:
# three arguments if it already has a unit there can't be
# a fraction for the amount
if len(tokens) > 2:
tokens = self.parse_tokens(tokens)
try:
if unit is not None:
# a unit is already found, no need to try the second argument for a fraction