create Transpose Words automation
This commit is contained in:
parent
8fa00972bd
commit
479cf1a042
@ -13,6 +13,7 @@ class IngredientParser:
|
|||||||
food_aliases = {}
|
food_aliases = {}
|
||||||
unit_aliases = {}
|
unit_aliases = {}
|
||||||
never_unit = {}
|
never_unit = {}
|
||||||
|
transpose_words = {}
|
||||||
|
|
||||||
def __init__(self, request, cache_mode, ignore_automations=False):
|
def __init__(self, request, cache_mode, ignore_automations=False):
|
||||||
"""
|
"""
|
||||||
@ -50,10 +51,22 @@ class IngredientParser:
|
|||||||
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():
|
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
|
self.never_unit[a.param_1] = a.param_2
|
||||||
caches['default'].set(NEVER_UNIT_CACHE_KEY, self.never_unit, 30)
|
caches['default'].set(NEVER_UNIT_CACHE_KEY, self.never_unit, 30)
|
||||||
|
|
||||||
|
TRANSPOSE_WORDS_CACHE_KEY = f'automation_transpose_words_{self.request.space.pk}'
|
||||||
|
if c := caches['default'].get(TRANSPOSE_WORDS_CACHE_KEY, None):
|
||||||
|
self.transpose_words = c
|
||||||
|
caches['default'].touch(TRANSPOSE_WORDS_CACHE_KEY, 30)
|
||||||
|
else:
|
||||||
|
i = 0
|
||||||
|
for a in Automation.objects.filter(space=self.request.space, disabled=False, type=Automation.TRANSPOSE_WORDS).only('param_1', 'param_2').order_by('order').all():
|
||||||
|
self.never_unit[i] = [a.param_1, a.param_2]
|
||||||
|
i += 1
|
||||||
|
caches['default'].set(TRANSPOSE_WORDS_CACHE_KEY, self.transpose_words, 30)
|
||||||
else:
|
else:
|
||||||
self.food_aliases = {}
|
self.food_aliases = {}
|
||||||
self.unit_aliases = {}
|
self.unit_aliases = {}
|
||||||
self.never_unit = {}
|
self.never_unit = {}
|
||||||
|
self.transpose_words = {}
|
||||||
|
|
||||||
def apply_food_automation(self, food):
|
def apply_food_automation(self, food):
|
||||||
"""
|
"""
|
||||||
@ -83,7 +96,7 @@ class IngredientParser:
|
|||||||
if self.ignore_rules:
|
if self.ignore_rules:
|
||||||
return unit
|
return unit
|
||||||
else:
|
else:
|
||||||
if self.unit_aliases:
|
if self.transpose_words:
|
||||||
try:
|
try:
|
||||||
return self.unit_aliases[unit]
|
return self.unit_aliases[unit]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
@ -249,15 +262,31 @@ class IngredientParser:
|
|||||||
|
|
||||||
return tokens
|
return tokens
|
||||||
|
|
||||||
def parse_tokens(self, tokens):
|
def apply_transpose_words_automations(self, ingredient):
|
||||||
"""
|
"""
|
||||||
parser that applies automations to unmodified tokens
|
If two words (param_1 & param_2) are detected in sequence, swap their position in the ingredient string
|
||||||
|
:param 1: first word to detect
|
||||||
|
:param 2: second word to detect
|
||||||
|
return: new ingredient string
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
####################################################
|
||||||
|
####################################################
|
||||||
|
####################################################
|
||||||
|
####################################################
|
||||||
if self.ignore_rules:
|
if self.ignore_rules:
|
||||||
return tokens
|
return ingredient
|
||||||
|
|
||||||
return self.apply_never_unit_automations(tokens)
|
else:
|
||||||
|
if self.transpose_words:
|
||||||
|
for rule in self.transpose_words:
|
||||||
|
ingredient = re.sub(rf"\b({rule[0]}) ({rule[1]})\b", r"\2 \1", ingredient)
|
||||||
|
|
||||||
|
else:
|
||||||
|
for rule in Automation.objects.filter(space=self.request.space, type=Automation.TRANSPOSE_WORDS, disabled=False).order_by('order'):
|
||||||
|
ingredient = re.sub(rf"\b({rule.param_1}) ({rule.param_2})\b", r"\2 \1", ingredient)
|
||||||
|
|
||||||
|
return ingredient
|
||||||
|
|
||||||
def parse(self, ingredient):
|
def parse(self, ingredient):
|
||||||
"""
|
"""
|
||||||
@ -275,6 +304,8 @@ class IngredientParser:
|
|||||||
if len(ingredient) == 0:
|
if len(ingredient) == 0:
|
||||||
raise ValueError('string to parse cannot be empty')
|
raise ValueError('string to parse cannot be empty')
|
||||||
|
|
||||||
|
ingredient = self.apply_transpose_words_automations(ingredient)
|
||||||
|
|
||||||
# some people/languages put amount and unit at the end of the ingredient string
|
# some people/languages put amount and unit at the end of the ingredient string
|
||||||
# if something like this is detected move it to the beginning so the parser can handle it
|
# if something like this is detected move it to the beginning so the parser can handle it
|
||||||
if len(ingredient) < 1000 and re.search(r'^([^\W\d_])+(.)*[1-9](\d)*\s*([^\W\d_])+', ingredient):
|
if len(ingredient) < 1000 and re.search(r'^([^\W\d_])+(.)*[1-9](\d)*\s*([^\W\d_])+', ingredient):
|
||||||
@ -311,7 +342,7 @@ class IngredientParser:
|
|||||||
# three arguments if it already has a unit there can't be
|
# three arguments if it already has a unit there can't be
|
||||||
# a fraction for the amount
|
# a fraction for the amount
|
||||||
if len(tokens) > 2:
|
if len(tokens) > 2:
|
||||||
tokens = self.parse_tokens(tokens)
|
tokens = self.apply_never_unit_automations(tokens)
|
||||||
try:
|
try:
|
||||||
if unit is not None:
|
if unit is not None:
|
||||||
# a unit is already found, no need to try the second argument for a fraction
|
# a unit is already found, no need to try the second argument for a fraction
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Generated by Django 4.1.7 on 2023-04-24 15:00
|
# Generated by Django 4.1.7 on 2023-04-24 16:22
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
@ -13,7 +13,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='automation',
|
model_name='automation',
|
||||||
name='type',
|
name='type',
|
||||||
field=models.CharField(choices=[('FOOD_ALIAS', 'Food Alias'), ('UNIT_ALIAS', 'Unit Alias'), ('KEYWORD_ALIAS', 'Keyword Alias'), ('DESCRIPTION_REPLACE', 'Description Replace'), ('INSTRUCTION_REPLACE', 'Instruction Replace'), ('NEVER_UNIT', 'Never Unit')], max_length=128),
|
field=models.CharField(choices=[('FOOD_ALIAS', 'Food Alias'), ('UNIT_ALIAS', 'Unit Alias'), ('KEYWORD_ALIAS', 'Keyword Alias'), ('DESCRIPTION_REPLACE', 'Description Replace'), ('INSTRUCTION_REPLACE', 'Instruction Replace'), ('NEVER_UNIT', 'Never Unit'), ('TRANSPOSE_WORDS', 'Transpose Words')], max_length=128),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='userpreference',
|
model_name='userpreference',
|
||||||
|
@ -1320,11 +1320,12 @@ class Automation(ExportModelOperationsMixin('automations'), models.Model, Permis
|
|||||||
DESCRIPTION_REPLACE = 'DESCRIPTION_REPLACE'
|
DESCRIPTION_REPLACE = 'DESCRIPTION_REPLACE'
|
||||||
INSTRUCTION_REPLACE = 'INSTRUCTION_REPLACE'
|
INSTRUCTION_REPLACE = 'INSTRUCTION_REPLACE'
|
||||||
NEVER_UNIT = 'NEVER_UNIT'
|
NEVER_UNIT = 'NEVER_UNIT'
|
||||||
|
TRANSPOSE_WORDS = 'TRANSPOSE_WORDS'
|
||||||
|
|
||||||
type = models.CharField(max_length=128,
|
type = models.CharField(max_length=128,
|
||||||
choices=((FOOD_ALIAS, _('Food Alias')), (UNIT_ALIAS, _('Unit Alias')), (KEYWORD_ALIAS, _('Keyword Alias')),
|
choices=((FOOD_ALIAS, _('Food Alias')), (UNIT_ALIAS, _('Unit Alias')), (KEYWORD_ALIAS, _('Keyword Alias')),
|
||||||
(DESCRIPTION_REPLACE, _('Description Replace')), (INSTRUCTION_REPLACE, _('Instruction Replace')),
|
(DESCRIPTION_REPLACE, _('Description Replace')), (INSTRUCTION_REPLACE, _('Instruction Replace')),
|
||||||
(NEVER_UNIT, _('Never Unit')),))
|
(NEVER_UNIT, _('Never Unit')), (TRANSPOSE_WORDS, _('Transpose Words')),))
|
||||||
name = models.CharField(max_length=128, default='')
|
name = models.CharField(max_length=128, default='')
|
||||||
description = models.TextField(blank=True, null=True)
|
description = models.TextField(blank=True, null=True)
|
||||||
|
|
||||||
|
@ -68,6 +68,17 @@ You can also create them manually by setting the following
|
|||||||
These rules are processed whenever you are importing recipes from websites or other apps
|
These rules are processed whenever you are importing recipes from websites or other apps
|
||||||
and when using the simple ingredient input (shopping, recipe editor, ...).
|
and when using the simple ingredient input (shopping, recipe editor, ...).
|
||||||
|
|
||||||
|
## Transpose Words
|
||||||
|
|
||||||
|
Some recipes list the food before the units for some foods (garlic cloves). This automation will transpose 2 words in an
|
||||||
|
ingredient so "garlic cloves" will automatically become "cloves garlic"
|
||||||
|
|
||||||
|
- **Parameter 1**: first word to detect
|
||||||
|
- **Parameter 2**: second word to detect
|
||||||
|
|
||||||
|
These rules are processed whenever you are importing recipes from websites or other apps
|
||||||
|
and when using the simple ingredient input (shopping, recipe editor, ...).
|
||||||
|
|
||||||
# Order
|
# Order
|
||||||
|
|
||||||
If the Automation type allows for more than one rule to be executed (for example description replace)
|
If the Automation type allows for more than one rule to be executed (for example description replace)
|
||||||
|
@ -527,5 +527,6 @@
|
|||||||
"plural_usage_info": "Use the plural form for units and food inside this space.",
|
"plural_usage_info": "Use the plural form for units and food inside this space.",
|
||||||
"Create Recipe": "Create Recipe",
|
"Create Recipe": "Create Recipe",
|
||||||
"Import Recipe": "Import Recipe",
|
"Import Recipe": "Import Recipe",
|
||||||
"Never_Unit": "Never Unit"
|
"Never_Unit": "Never Unit",
|
||||||
|
"Transpose_Words": "Transpose Words"
|
||||||
}
|
}
|
||||||
|
@ -558,6 +558,8 @@ export class Models {
|
|||||||
{ value: "KEYWORD_ALIAS", text: "Keyword_Alias" },
|
{ value: "KEYWORD_ALIAS", text: "Keyword_Alias" },
|
||||||
{ value: "DESCRIPTION_REPLACE", text: "Description_Replace" },
|
{ value: "DESCRIPTION_REPLACE", text: "Description_Replace" },
|
||||||
{ value: "INSTRUCTION_REPLACE", text: "Instruction_Replace" },
|
{ value: "INSTRUCTION_REPLACE", text: "Instruction_Replace" },
|
||||||
|
{ value: "NEVER_UNIT", text: "Never_Unit" },
|
||||||
|
{ value: "TRANSPOSE_WORDS", text: "Transpose_Words" },
|
||||||
],
|
],
|
||||||
field: "type",
|
field: "type",
|
||||||
label: "Type",
|
label: "Type",
|
||||||
|
Loading…
Reference in New Issue
Block a user