grocy-cli/grocy/cli.py

198 lines
6.1 KiB
Python
Raw Normal View History

import click
2019-04-28 16:12:05 -05:00
from markdown import markdown
2019-04-01 00:16:32 -05:00
from jinja2 import Environment, FileSystemLoader
2019-06-16 23:54:10 -05:00
from grocy.conf import Configuration
from grocy.recipe import Recipe
from grocy.table import Table
from grocy.entity import Entity
from grocy.stock import Stock
import yaml
from sys import exit
2019-06-16 23:54:10 -05:00
from os import path
import logging
APP_NAME = 'grocy-cli'
SAMPLE_CONFIG_FILE = 'sample.config.yml'
2019-04-01 00:16:32 -05:00
TMP_DIR = '/tmp/grocy'
CONFIG_FILE = 'config.yml'
CONFIG_DIR = click.get_app_dir(APP_NAME)
PROJ_DIR = path.join(path.dirname(path.realpath(__file__)))
2019-06-16 23:54:10 -05:00
TEMPLATE_LOADER = Environment(loader=FileSystemLoader('templates'), trim_blocks=True, lstrip_blocks=True)
2019-03-09 19:02:42 -06:00
def __validate_token(cfg):
# Validate token
if hasattr(cfg, 'token') or cfg['token'] is None:
click.echo('No token was found. Please add your token to the config file', err=True)
2019-06-16 23:54:10 -05:00
#logger.error('No token was found. Please add your token')
2019-03-09 19:02:42 -06:00
exit(1)
@click.group()
2019-06-16 23:54:10 -05:00
def main():
cfg = Configuration()
if not cfg.exists:
no_config_msg = 'A config file was not found. A sample configuration file'
no_config_msg += ' will be created under {}. Is that Ok?'.format(cfg.CONFIG_DIR)
create_config_app_dir = click.confirm(no_config_msg)
2019-06-16 23:54:10 -05:00
user_cfg_options = {}
if create_config_app_dir:
2019-06-16 23:54:10 -05:00
user_cfg_options['logger_level'] = click.prompt('Enter logger level',
default='DEBUG')
user_cfg_options['logger_file_location'] = click.prompt('Enter location for logger',
default=path.expanduser('~/.config/grocy/log'))
user_cfg_options['api'] = click.prompt('Enter the grocy api url',
default='https://demo-en.grocy.info/api')
user_cfg_options['token'] = click.prompt('Enter the grocy token ',
default='')
user_cfg_options['col_format'] = click.prompt('Enter the col position for rendering tables',
default='col')
user_cfg_options['table_format'] = click.prompt('Enter the table format',
default='simple')
cfg.create(user_cfg_options)
else:
exit(0)
2019-06-16 23:54:10 -05:00
else:
cfg.load()
2019-03-09 19:02:42 -06:00
2019-06-16 23:54:10 -05:00
logging.basicConfig(level=cfg.logger_level, filename=cfg.logger_file_location)
@main.command()
2019-06-16 23:54:10 -05:00
@click.pass_context
2019-03-09 19:02:42 -06:00
def stock(ctx):
2019-06-16 23:54:10 -05:00
logger = logging.getLogger('cli.stock')
if ctx.invoked_subcommand is None:
try:
entity = Stock()
stocks = entity.get()
table = Table(stocks=stocks)
click.echo(table.stock)
except Exception as e:
logger.error(e)
raise e
2019-03-09 19:02:42 -06:00
@main.command()
2019-06-16 23:54:10 -05:00
def shopping():
logger = logging.getLogger('cli.shopping')
try:
entity = Entity(name='shopping_list')
shopping_list = entity.get()
table = Table(shopping_list=shopping_list)
click.echo(table.shopping_list)
except Exception as e:
logger.error(e)
raise e
@main.group()
def ingredient(ctx):
pass
@ingredient.command('add')
@click.option('-r', '--recipe_id')
def add(ctx, recipe_id):
logger = logging.getLogger('cli.ingredient.add')
try:
loaded_template = TEMPLATE_LOADER.get_template('ingredient_add.yml')
if recipe_id:
entity = Entity(name='recipes')
recipe = entity.get(id=recipe_id)
new_ingredient = click.edit(loaded_template.render(recipe))
parsed_new_ingredient = yaml.safe_load(new_ingredient)
else:
new_ingredient = click.edit(loaded_template.render())
parsed_new_ingredient = yaml.safe_load(new_ingredient)
if parsed_new_ingredient['recipe_id']:
raise Exception('Recipe id is not defined')
if new_ingredient:
entity = Entity(name='ingredients', **parsed_new_ingredient)
entity.create()
except Exception as e:
logger.error(e)
2019-03-09 19:02:42 -06:00
2019-04-01 00:16:32 -05:00
@main.group()
2019-03-09 19:02:42 -06:00
@click.pass_context
def recipe(ctx):
2019-06-16 23:54:10 -05:00
pass
2019-03-09 19:02:42 -06:00
2019-06-16 23:54:10 -05:00
@recipe.command('ls')
def ls():
logger = logging.getLogger('cli.recipe')
try:
entity = Entity(name='recipes')
recipes = entity.get()
recipe = Recipe()
recipes_reqs = recipe.get_requirements()
table = Table(recipes=recipes, recipes_reqs=recipes_reqs)
click.echo(table.recipe)
except Exception as e:
logger.error(e)
raise e
2019-03-09 19:50:42 -06:00
2019-04-01 00:16:32 -05:00
@recipe.command('edit')
@click.argument('recipe_id')
2019-06-16 23:54:10 -05:00
def edit(recipe_id):
logger = logging.getLogger('cli.recipe.edit')
2019-04-01 00:16:32 -05:00
try:
if recipe_id:
2019-06-16 23:54:10 -05:00
entity = Entity(name='recipes')
recipe = entity.get(id=recipe_id)
2019-05-05 16:06:33 -05:00
loaded_template = TEMPLATE_LOADER.get_template('recipe_edit.yml')
2019-06-16 23:54:10 -05:00
edited_recipe = click.edit(loaded_template.render(recipe))
2019-04-01 00:16:32 -05:00
if edited_recipe is not None:
2019-04-28 16:12:05 -05:00
parsed_edited_recipe = yaml.safe_load(edited_recipe)
parsed_edited_recipe['description'] = markdown(parsed_edited_recipe['description'])
recipe.__dict__.update(parsed_edited_recipe)
recipe.update()
2019-04-01 00:16:32 -05:00
except Exception as e:
logger.error(e)
logger.error('Could not edit recipe {}'.format(recipe_id))
2019-06-16 23:54:10 -05:00
raise e
2019-05-05 16:06:33 -05:00
@recipe.command('create')
@click.pass_context
def create(ctx):
2019-06-16 23:54:10 -05:00
logger = logging.getLogger('cli.recipe.create')
2019-05-05 16:06:33 -05:00
try:
2019-06-16 23:54:10 -05:00
recipe = Entity(name='recipes')
2019-05-05 16:06:33 -05:00
loaded_template = TEMPLATE_LOADER.get_template('recipe_add.yml')
new_recipe = click.edit(loaded_template.render())
if new_recipe is not None:
parsed_new_recipe = yaml.safe_load(new_recipe)
parsed_new_recipe['description'] = markdown(parsed_new_recipe['description'])
recipe.__dict__.update(parsed_new_recipe)
recipe.create()
except Exception as e:
logger.error(e)
2019-06-16 23:54:10 -05:00
raise e
2019-05-05 16:06:33 -05:00
#@main.command()
#@click.pass_context
#def chore(ctx):
# cfg = ctx.obj['cfg']
#
# chore = Chore(**cfg)
# chores = chore.get_list()
# click.echo(chores)
#
#@main.command()
#@click.pass_context
#def task(ctx):
# cfg = ctx.obj['cfg']
#
# task = Task(**cfg)
# tasks = task.get_list()
# click.echo(tasks)