Пример #1
0
def _get_linked_recipe(ingredient: Ingredient,
                       *,
                       base_url: URL,
                       parser: RecipeParser,
                       flatten: bool = True) -> Recipe:
    url = base_url.join(URL(ingredient.link))
    try:
        with urllib.request.urlopen(str(url)) as req:
            encoding = req.info().get_content_charset() or 'UTF-8'
            src = req.read().decode(encoding)
    except Exception as e:
        raise RuntimeError(
            f'''Couldn't find linked recipe for ingredient "{ingredient.name}"'''
        ) from e

    try:
        link_recipe = parser.parse(src)
    except Exception as e:
        raise RuntimeError(
            f'''Couldn't parse linked recipe for ingredient "{ingredient.name}"'''
        ) from e

    if flatten:
        link_recipe = _get_flattened_recipe(link_recipe,
                                            base_url=url,
                                            parser=parser)

    if ingredient.amount:
        try:
            link_recipe = get_recipe_with_yield(link_recipe, ingredient.amount)
        except StopIteration:
            print(_make_missing_yield_warning(link_recipe, ingredient.amount),
                  file=sys.stderr)

    return link_recipe
Пример #2
0
def main():
    # completions
    argcomplete.autocomplete(parser)

    # parse args
    args = parser.parse_args()

    # initialize
    rp = RecipeParser()
    rs = RecipeSerializer()

    # read and parse recipe
    src = args.file.read()
    r = rp.parse(src)

    # scale recipe
    r = _process_scaling(r, args)

    # base url for late use
    base_url = URL(f'file://{os.path.abspath(args.file.name)}')

    # export linked recipes
    if args.export_links:
        _export_links(r, args, base_url, rp, rs)
        return

    # flatten recipe
    if args.flatten:
        r = _get_flattened_recipe(r, base_url=base_url, parser=rp)

    # create output depending on arguments
    print(_create_recipe_output(r, rs, args))
Пример #3
0
def main():
    parser = argparse.ArgumentParser(description='Read and process recipemd recipes')

    parser.add_argument(
        'file', type=argparse.FileType('r', encoding='UTF-8'), help='A recipemd file'
    ).completer = FilesCompleter(allowednames='*.md')

    display_parser = parser.add_mutually_exclusive_group()
    display_parser.add_argument('-t', '--title', action='store_true', help='Display recipe title')
    display_parser.add_argument('-i', '--ingredients', action='store_true', help='Display recipe ingredients')

    parser.add_argument(
        '-f', '--flatten', action='store_true',
        help='Flatten ingredients and instructions of linked recipes into main recipe'
    )

    parser.add_argument(
        '-r', '--round', type=lambda s: None if s.lower() == 'no' else int(s), metavar='n', default=2,
        help='Round amount to n digits after decimal point. Default is "2", use "no" to disable rounding.'
    ).completer = ChoicesCompleter(('no', *range(0, decimal.getcontext().prec + 1)))

    scale_parser = parser.add_mutually_exclusive_group()
    scale_parser.add_argument('-m', '--multiply', type=str, help='Multiply recipe by N', metavar='N')
    scale_parser.add_argument(
        '-y', '--yield', type=str, help='Scale the recipe for yield Y, e.g. "5 servings"',
        metavar='Y', dest='required_yield'
    ).completer = _yield_completer

    # completions
    argcomplete.autocomplete(parser)

    # parse args
    args = parser.parse_args()

    # read and parse recipe
    src = args.file.read()
    rp = RecipeParser()
    r = rp.parse(src)

    # scale recipe
    r = _process_scaling(r, args)

    # flatten recipe
    if args.flatten:
        base_url = URL(f'file://{os.path.abspath(args.file.name)}')
        r = _get_flattened_ingredients_recipe(r, base_url=base_url, parser=rp)

    # create output depending on arguments
    if args.title:
        print(r.title)
    elif args.ingredients:
        for ingr in r.leaf_ingredients:
            print(_ingredient_to_string(ingr, rounding=args.round))
    else:
        rs = RecipeSerializer()
        print(rs.serialize(r, rounding=args.round))
Пример #4
0
def get_filtered_recipes(args):
    rp = RecipeParser()
    result = []
    for path in glob.glob(os.path.join(args.folder, '**/*.md'), recursive=True):
        try:
            with open(path, 'r', encoding='UTF-8') as file:
                recipe = rp.parse(file.read())
            tags = recipe.tags
            if evaluate(args.filter, tags):
                result.append((recipe, os.path.relpath(path, args.folder)))
        except Exception as e:
            if not args.no_messages:
                print(f"An error occurred, skipping {os.path.relpath(path, args.folder)}: {e.args[0]}", file=sys.stderr)
    return result
Пример #5
0
def _get_linked_recipe(ingredient: Ingredient, *, base_url: URL, parser: RecipeParser, flatten: bool=True) -> Recipe:
    url = base_url.join(URL(ingredient.link))
    try:
        with urllib.request.urlopen(str(url)) as req:
            encoding = req.info().get_content_charset() or 'UTF-8'
            src = req.read().decode(encoding)
    except Exception as e:
        raise RuntimeError(f'''Couldn't find linked recipe for ingredient "{ingredient.name}"''') from e

    try:
        link_recipe = parser.parse(src)
    except Exception as e:
        raise RuntimeError(f'''Couldn't parse linked recipe for ingredient "{ingredient.name}"''') from e

    if flatten:
        link_recipe = _get_flattened_ingredients_recipe(link_recipe, base_url=url, parser=parser)

    return link_recipe
Пример #6
0
def main():
    parser = argparse.ArgumentParser(
        description='Read and process recipemd recipes')

    parser.add_argument('file', type=open, help='A recipemd file')
    display_parser = parser.add_mutually_exclusive_group()
    display_parser.add_argument('-t',
                                '--title',
                                action='store_true',
                                help='Display recipe title')
    display_parser.add_argument('-i',
                                '--ingredients',
                                action='store_true',
                                help='Display recipe ingredients')

    scale_parser = parser.add_mutually_exclusive_group()
    scale_parser.add_argument('-m',
                              '--multiply',
                              type=str,
                              help='Multiply recipe by N',
                              metavar='N')
    scale_parser.add_argument('-y',
                              '--yield',
                              type=str,
                              help='Scale the recipe for yield Y',
                              metavar='Y',
                              dest='required_yield')

    args = parser.parse_args()

    src = args.file.read()

    rp = RecipeParser()
    r = rp.parse(src)

    if args.required_yield is not None:
        required_yield = RecipeParser.parse_amount(args.required_yield)
        if required_yield is None or required_yield.factor is None:
            print(f'Given yield is not valid', file=sys.stderr)
            exit(1)
        matching_recipe_yield = next(
            (y for y in r.yields if y.unit == required_yield.unit), None)
        if matching_recipe_yield is None:
            if required_yield.unit is None:
                matching_recipe_yield = Amount(Decimal(1))
            else:
                print(
                    f'Recipe "{r.title}" does not specify a yield in the unit "{required_yield.unit}". The '
                    f'following units can be used: ' +
                    ", ".join(f'"{y.unit}"' for y in r.yields),
                    file=sys.stderr)
                exit(1)
        r = multiply_recipe(
            r, required_yield.factor / matching_recipe_yield.factor)
    elif args.multiply is not None:
        multiply = RecipeParser.parse_amount(args.multiply)
        if multiply is None or multiply.factor is None:
            print(f'Given multiplier is not valid', file=sys.stderr)
            exit(1)
        if multiply.unit is not None:
            print(f'A recipe can only be multiplied with a unitless amount',
                  file=sys.stderr)
            exit(1)
        r = multiply_recipe(r, multiply.factor)

    if args.title:
        print(r.title)
    elif args.ingredients:
        for ingr in r.leaf_ingredients:
            print(_ingredient_to_string(ingr))
    else:
        rs = RecipeSerializer()
        print(rs.serialize(r))
Пример #7
0
from recipemd.data import RecipeParser
from unidecode import unidecode

root_path = '.'
rp = RecipeParser()

tt = str.maketrans({
    "ä": "ae",
    "ö": "oe",
    "ü": "ue",
    "Ä": "Ae",
    "Ö": "Oe",
    "Ü": "Ue",
    "ß": "ss",
})

for path in glob.glob(os.path.join(root_path, '**/*.md'), recursive=True):
    try:
        with open(path, 'r', encoding='UTF-8') as file:
            recipe = rp.parse(file.read())
            filename = recipe.title
            filename = filename.translate(tt)
            filename = unidecode(filename)
            filename = re.sub(r'[^a-zA-Z0-9]+', '_', filename)
            filename = re.sub(r'^_+|_+$', '', filename)
            new_path = os.path.join(os.path.dirname(path), f'{filename}.md')
            os.rename(path, new_path)
    except Exception as e:
        print(f'[Filenames] Ignoring {path}', file=sys.stderr)
        pprint(e, stream=sys.stderr)