ocp5/cli.py

159 lines
4.3 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Author: freezed <freezed@users.noreply.github.com> 2018-08-04
Version: 0.1
Licence: `GNU GPL v3` GNU GPL v3: http://www.gnu.org/licenses/
Command line interface to interact with local DB
Choose a product in a list of aivaiable categories['results_list'],
the system gives you an alternative with a better 'nutriscore'.
You can save this product to get it later.
"""
from os import system
from db import Db
from config import DB_REQUEST, CLI_MSG_DISCLAIMER, CLI_MSG_ASK_CAT, \
CLI_MSG_ASK_ERR, CLI_MSG_QUIT, CLI_MSG_CHOOSEN_CAT
cli_msg = str()
def ask_user(head_msg, foot_msg, item_list, db_obj=None):
"""
Ask user to choose an item in the provided list, using numeric index
:head_msg: Text displayed in header
:foot_msg: Text displayed in footer
:item_list: Dict() containing all data about item (see `get_data_list()`)
:db_obj: Database object (optionnal)
:result:
- item:
- cli_msg:
- valid_item:
"""
valid_input = False
if db_obj is not None:
db_msg = db_obj.message
else:
db_msg = ""
while valid_input is False:
system('clear')
print(db_msg)
print(head_msg)
print(item_list['results_txt'])
print(foot_msg)
user_input = input(CLI_MSG_ASK_CAT.format(item_list['max_id']))
if user_input.lower() == "q":
valid_input = True
valid_item = False
item = ""
else:
try:
user_input = int(user_input)
# Response not int(), re-ask
except ValueError:
foot_msg += CLI_MSG_ASK_ERR.format(user_input)
else:
# Response is valid
if user_input <= item_list['max_id']:
valid_input = True
valid_item = True
item = item_list['results_list'][user_input]
foot_msg = CLI_MSG_CHOOSEN_CAT.format(item[1])
# Response not in range, re-ask
else:
foot_msg += CLI_MSG_ASK_ERR.format(user_input)
return {
'item': item,
'cli_msg': foot_msg,
'valid_item': valid_item
}
def get_data_list(db_obj, sql):
"""
Gets data from DB & return them formated as a text list displayable on CLI
:db_obj: a database object [PyMySQL]
:sql: a SQL query
:Return: a dict containing details on requested data:
- max_id: maximum ID
- results_list: stored in a list of tuple (id, name, count)
- results_txt: in a string, text-formated
"""
db_obj.execute(sql)
max_id = int(db_obj.cursor.rowcount - 1)
results_list = [(idx, val['name'], val['COUNT(*)'])
for idx, val in enumerate(db_obj.result)]
# Hacky results-split for rendering in 2 columns
res_even = [(idx, val['name'], val['COUNT(*)'])
for idx, val in enumerate(db_obj.result) if idx % 2 == 0]
res_uneven = [(idx, val['name'], val['COUNT(*)'])
for idx, val in enumerate(db_obj.result) if idx % 2 != 0]
# category list
results_txt = ""
for num, unused in enumerate(res_uneven):
results_txt += "{} : {} \t\t {} : {}\n".format(
res_even[num][0],
res_even[num][1],
res_uneven[num][0],
res_uneven[num][1]
)
if len(res_uneven) < len(res_even):
num += 1
results_txt += "{} : {}\n".format(
res_even[num][0],
res_even[num][1]
)
return {
'max_id': max_id,
'results_list': results_list,
'results_txt': results_txt
}
# Starts a DB connection
LOCAL_DB = Db()
# category list
category_list = get_data_list(LOCAL_DB, DB_REQUEST['list_cat'])
# Prompts it with an index
# Asks the user to enter the index of the selected category
category_asked = ask_user(CLI_MSG_DISCLAIMER, cli_msg, category_list, LOCAL_DB)
# Lists all products
if category_asked['valid_item']:
cli_msg = CLI_MSG_CHOOSEN_CAT.format(category_asked['item'][1])
else:
cli_msg = CLI_MSG_QUIT
# Asks the user to enter the index of the selected product
# If index is not valid, re-ask
# Shows the 1st product in the same category with the lowest nutriscore
# Saves if user choose it
print(cli_msg)