#!/usr/bin/env python # -*- coding: utf-8 -*- import csv import argparse from clint.textui import puts, colored, indent from clint.textui import columns #import pytz #import tzlocal import time from datetime import datetime, timedelta, date import dateutil.parser from dateutil.rrule import rrulestr #from icalendar import Calendar,Event,Todo,Journal,Alarm #import caldav #import uuid #import json import os #os.environ['LANGUAGE']='fr' #import logging import sys #import re #import urllib3 #from getpass import getpass #from sympy import symbols #from sympy.plotting import textplot import subprocess from subprocess import Popen, PIPE import numpy as np import gettext #gettext.bindtextdomain('base', 'locale/en/LC_MESSAGES/base.mo') #gettext.bindtextdomain('base', '.') #gettext.textdomain('base') gettext.find('base') # Voir : https://docs.python.org/fr/3/library/gettext.html origindir = os.path.dirname(os.path.abspath(__file__)) localedir = os.path.dirname(os.path.abspath(__file__))+"/locale/" #print(localedir) en = gettext.translation('base', localedir=localedir, languages=['en']) #en = gettext.translation('base', localedir='locale', languages=['en']) en.install() _ = en.gettext # english # fr = gettext.translation('base', localedir='locale/', languages=['fr']) # fr.install() # _ = fr.gettext # english # Voir : https://medium.com/i18n-and-l10n-resources-for-developers/how-to-translate-python-applications-with-the-gnu-gettext-module-5c1c085041 """ This program allow you to store and visualise your weight. No database is necessary because all is stored in files. Three files are important : - weight-cli.py, the principal program - data2.csv, the data file and - Fonctionnel.txt, the code for Gnuplot But other files are present, as personal.txt with your other parameters. A measure is characterized by : - its value - its type - its date - its metrics - its identifier - one comment - other Actually, weight-cli allow to add or remove a measure, visualise all the measure, plot a graph of these. To know witch parameters are available, type : weight-cli --help or weight-cli -h """ def save_file_data(): """ Saving the data file name """ f = open(origindir+"/Fonctionnel.txt", "r") contents = f.readlines() f.close() linenum = 0 for row in contents: if row.split(' ',1)[0] == 'plot': contents.insert(linenum, "plot '"+origindir+'/'+str(args.data)+"' using 3:1 w dots title '', f(x) lc 'red' w dots title 'bmi max'\n") del(contents[linenum+1]) linenum += 1 f = open(origindir+"/Fonctionnel.txt", "w") contents = "".join(contents) f.write(contents) f.close() def save_mesure(): """ Displaying and recording a measure """ print(_("Your measure has been recorded")) with indent(4, quote=colored.blue('')): puts(colored.green("-your weight : {weight} kg").format(weight=args.weight)) puts("-its type : {typ}".format(typ=args.type)) puts("-the date : {dat}".format(dat=args.date)) puts("-the metric : {metric}".format(metric=args.metric)) puts("-the identifier : {ide}".format(ide=args.id)) puts("-your comment : {comment}".format(comment=args.comment)) puts("-other : {other}".format(other=args.other)) with open(origindir+'/'+str(args.data), 'a', newline='\n') as csvfile: weightwriter = csv.writer(csvfile, delimiter='|', quotechar='"', quoting=csv.QUOTE_MINIMAL) weightwriter.writerow([str(args.weight), \ str(args.type), \ str(datetime.now().strftime("%Y-%m-%d %H:%M:%S")), \ str(args.metric), str(args.id), \ str(args.comment), \ str(args.other)]) def read_measures(): """ Display of all measures """ data_file = open(origindir+'/'+str(args.data), 'r') data = csv.reader(data_file, delimiter='|') linenum = 0 for row in data: with indent(2, quote=colored.blue('')): puts(columns([(colored.red(str(linenum))), 4], \ [(colored.green(str(row[0])+' kg')), 15], \ [(str(row[1])),10], \ [(colored.yellow(str(row[2]))),25], \ [(str(row[3])),6], \ [(str(row[4])),4], \ [(colored.magenta(str(row[5]))),20])), \ [(str(row[6])),10] linenum += 1 data_file.close() def remove_measure(): """ Remove a measure """ f = open(origindir+'/'+str(args.data), "r") contents = f.readlines() f.close() # remove the line item from list, by line number, starts from 0 store_temp = str(args.remove)+' '+contents[args.remove] g = open(origindir+'/remove.txt', "w") g.write(str(store_temp)) g.close() contents.pop(args.remove) f = open(origindir+'/'+str(args.data), "w") contents = "".join(contents) f.write(contents) f.close() def undo_remove(): """ Undo remove the last line removed """ f = open(origindir+'/'+str(args.data), "r") contents = f.readlines() f.close() g = open(origindir+'/remove.txt', 'r') store_temp = g.readline().split(' ',1) g.close() # insert the line item from list, by its line number contents.insert(int(store_temp[0]), store_temp[1]) f = open(origindir+'/'+str(args.data), "w") contents = "".join(contents) f.write(contents) f.close() def plot_graph(): """ Plot the graph of the weight evolution with Gnuplot """ if args.dates != None: print(args.dates) # set xrange [*:*] f = open(origindir+"/Fonctionnel.txt", "r") contents = f.readlines() f.close() linenum = 0 for row in contents: motif = row.split(' ',2)[0]+' '+row.split(' ',2)[1] if motif == 'set xrange': if args.dates[0] == '*': ligne = "set xrange [*:'"+args.dates[1]+"']\n" elif args.dates[1] == '*': ligne = "set xrange ['"+args.dates[0]+"':*]\n" else: ligne = "set xrange ['"+args.dates[0]+"':'"+args.dates[1]+"']\n" contents.insert(linenum, ligne) del(contents[linenum+1]) linenum += 1 f = open(origindir+"/Fonctionnel.txt", "w") contents = "".join(contents) f.write(contents) f.close() else: f = open(origindir+"/Fonctionnel.txt", "r") contents = f.readlines() f.close() linenum = 0 for row in contents: motif = row.split(' ',2)[0]+' '+row.split(' ',2)[1] if motif == 'set xrange': contents.insert(linenum, "set xrange [*:*]\n") del(contents[linenum+1]) linenum += 1 f = open(origindir+"/Fonctionnel.txt", "w") contents = "".join(contents) f.write(contents) f.close() #process = Popen(['gnuplot', 'Fonctionnel.txt'], stdout=PIPE, stderr=PIPE) process = Popen(['gnuplot', origindir+'/Fonctionnel.txt'])#, stdout=PIPE, stderr=PIPE) stdout, stderr = process.communicate() #print(stdout) def save_size(): print(bmi_weight_max()) """ Store the size """ f = open(origindir+'/personal.txt', "w") f.write(str(args.size)) f.close() f = open(origindir+"/Fonctionnel.txt", "r") contents = f.readlines() f.close() linenum = 0 for row in contents: motif = row.split(' ',2)[0]+' '+row.split(' ',2)[1] if motif == 'f(x) =': contents.insert(linenum, "f(x) = "+str(bmi_weight_max())+"\n") del(contents[linenum+1]) linenum += 1 f = open(origindir+"/Fonctionnel.txt", "w") contents = "".join(contents) f.write(contents) f.close() def tests_subproc(): """ Test of the subprocess module """ process = Popen(['cat', origindir+'/data2.csv'], stdout=PIPE, stderr=PIPE) stdout, stderr = process.communicate() print(stdout) def bmi(the_weight): """ Return the BMI for a given size """ f = open(origindir+'/personal.txt', "r") the_size = float(f.read()) f.close() bmi = the_weight / pow(the_size, 2) return(bmi) def bmi_weight_max(): """ Return the weight for BMI max """ f = open(origindir+'/personal.txt', "r") the_size = float(f.read()) f.close() weight_max = 29.9 * pow(the_size, 2) return(weight_max) ### Main ### """ Weight Recording Program Be careful, the data.csv file has a header line that lacks a final | separator for the number of fields to be correct. """ # Creating the parser for arguments parser = argparse.ArgumentParser() texte = _('A script to manage your weight in command line.') parser.description=texte # Creating arguments parser.add_argument('-da', '--data', default=origindir+'/data.csv', help=_('optional : file data') ) parser.add_argument('-s', '--size', type=float, default=-1, help=_('optional : size in meter') ) parser.add_argument('-w', '--weight', type=float, default=-1, help=_('optional : weight in kilogram') ) parser.add_argument('-t', '--type', default='WEIGHT', help=_('optional : type') ) parser.add_argument('-d', '--date', default=datetime.now().strftime("%Y-%m-%d %H:%M:%S"), help=_('optional : date') ) parser.add_argument('-i', '--id', default='', help=_('optional : id') ) parser.add_argument('-m', '--metric', default='true', help=_('optional : metric') ) parser.add_argument('-c', '--comment', default=' ', help=_('optional : comment') ) parser.add_argument('-o', '--other', default='', help=_('optional : other') ) parser.add_argument('-r', '--read', help='optional read measures', action='store_true' ) parser.add_argument('-rem', '--remove', type=int, default='-1', help=_('optional : delete a measure by its number in the list') ) parser.add_argument('-g', '--graph', help=_('optional : plot graph'), action='store_true' ) parser.add_argument('-ds', '--dates', nargs='+', help=_("optional : min_date max_date -> 'Y-m-d hh:mm:ss' or '*' for an automatic date.") ) parser.add_argument('-tst', '--tests', help='optional tests operations', action='store_true' ) parser.add_argument('-ur', '--undoremove', help=_('optional : undo remove the last line removed'), action='store_true' ) parser.add_argument('-v', '--version', version='0.0.5', action='version' ) # Argument retrieval args = parser.parse_args() # Launching of actions if args.data != 'data2.csv': save_file_data() if args.size != -1: save_size() if args.weight != -1: save_mesure() if args.read: read_measures() if args.remove >= 0: remove_measure() if args.graph: plot_graph() if args.tests: tests_subproc() if args.undoremove: undo_remove()