Compare commits

...

3 Commits

Author SHA1 Message Date
a54b19b938 making main less complex 2024-06-19 22:53:43 +02:00
bb5364d021 adding current date as default for cli args 2024-06-19 15:49:20 +02:00
6fa1c5a4c3 restructuring 2024-06-19 15:01:38 +02:00
7 changed files with 116 additions and 80 deletions

90
main.py
View File

@@ -1,95 +1,37 @@
#!/usr/bin/python3
import argparse
from lib.DataStore import DataStore
from lib.TimeSlot import TimeSlot
from lib.ui import convert_to_table
from datetime import datetime
from util.str_to_datetime import datetime
from model.TimeSlotContainer import time_slot_container as tsc
from model.TimeSlot import TimeSlot
def create_parser():
# Create the top-level parser
parser = argparse.ArgumentParser(description="Time tracker.")
subparsers = parser.add_subparsers(dest="command", help="Sub-command help")
# Create the parser for the "ls" command
_ = subparsers.add_parser("ls", help="List all events.")
# Create the parser for the "ps" command
_ = subparsers.add_parser("ps", help="Show the currently running event.")
# Create the parser for the "add" command
parser_add = subparsers.add_parser("add", help="Adding a new event.")
parser_add.add_argument("name", help="Name of the event")
parser_add.add_argument("-s", "--start", help="Start datetime (default now)")
parser_add.add_argument("-e", "--end", help="End datetime")
# Create the parser for the "start" command
parser_start = subparsers.add_parser("start", help="Starting a new event.")
parser_start.add_argument("name", help="Name of the event")
parser_start.add_argument("-s", "--start", help="Start datetime (default now)")
# Create the parser for the "end" command
parser_end = subparsers.add_parser("end", help="Ending the current event.")
parser_end.add_argument("-e", "--end", help="End datetime")
return parser
from util.views import convert_to_table
from util.parser import create_parser
if __name__ == "__main__":
parser = create_parser()
args = parser.parse_args()
ds = DataStore("data.json")
if args.command == "ls":
print(convert_to_table(ds.get_all_time_slots()))
print(convert_to_table(tsc.get_time_slots_by_date()))
elif args.command == "start":
time_slots = ds.get_all_time_slots()
running = list(filter(lambda x: x.end is None, time_slots))
if len(running):
print("An event is already running.")
if args.start is not None:
tsc.open_time_slot(args.name, datetime(args.start))
else:
if args.start is not None:
s = datetime.strptime(args.start, '%d.%m.%y %H:%M')
ds.add_time_slot(TimeSlot(args.name, start=s))
else:
ds.add_time_slot(TimeSlot(args.name))
print(f"Started event {args.name}.")
tsc.open_time_slot(args.name)
print(f"Started event {args.name}.")
elif args.command == "end":
time_slots = ds.get_all_time_slots()
running = list(filter(lambda x: x.end is None, time_slots))
if len(running) <= 0:
print("No running event.")
elif len(running) > 1:
raise Exception("Found multiple running event.")
if args.end is not None:
tsc.close_time_slot(datetime(args.end))
else:
if args.end is not None:
s = datetime.strptime(args.end, '%d.%m.%y %H:%M')
running[0].end = s
else:
running[0].end_now()
ds.write_update()
print(f"Ended event {running[0].name}.")
tsc.close_time_slot()
print("Ended event.")
elif args.command == "ps":
time_slots = ds.get_all_time_slots()
running = list(filter(lambda x: x.end is None, time_slots))
print(convert_to_table(running))
print(convert_to_table(tsc.get_open_time_slots()))
elif args.command == "add":
time_slots = ds.get_all_time_slots()
running = list(filter(lambda x: x.end is None, time_slots))
if len(running) > 0 and args.end is None:
print("An event is already running.")
else:
ts = TimeSlot(args.name)
if args.start is not None:
ts.start = datetime.strptime(args.start, '%d.%m.%y %H:%M')
if args.end is not None:
ts.end = datetime.strptime(args.end, '%d.%m.%y %H:%M')
ds.add_time_slot(ts)
ds.write_update()
print("The event was added.")
tsc.add_time_slot(args.name, datetime(args.start), datetime(args.end))

View File

@@ -1,5 +1,5 @@
from pathlib import Path
from .TimeSlot import TimeSlot
from model.TimeSlot import TimeSlot
import json
@@ -30,11 +30,9 @@ class DataStore:
def add_time_slot(self, time_slot: TimeSlot):
self._time_slots.append(time_slot)
self.write_update()
def remove_time_slot(self, time_slot: TimeSlot):
self._time_slots.remove(time_slot)
self.write_update()
def get_all_time_slots(self):
def get_all_time_slots(self) -> list[TimeSlot]:
return self._time_slots[:]

View File

@@ -0,0 +1,47 @@
from datetime import date, datetime
from model.DataStore import DataStore
from model.TimeSlot import TimeSlot
class TimeSlotContainer:
def __init__(self, ds: DataStore):
self._ds = ds
def get_open_time_slots(self) -> list[TimeSlot]:
return [ts for ts in self._ds.get_all_time_slots() if ts.end is None]
def get_all_time_slots(self) -> list[TimeSlot]:
return self._ds.get_all_time_slots()
def get_time_slots_by_date(self, d: date = datetime.now().date()):
return [ts for ts in self._ds.get_all_time_slots()
if ts.start.date() == datetime.now().date()]
def open_time_slot(self, name: str, start_dt: datetime = datetime.now()):
if len(self.get_open_time_slots()) > 0:
raise Exception("Ein event ist bereits aktiv.")
ts = TimeSlot(name)
ts.start = start_dt
self._ds.add_time_slot(ts)
self._ds.write_update()
def close_time_slot(self, end_dt: datetime = datetime.now()):
ts = self.get_open_time_slots()[0]
self._ds.remove_time_slot(ts)
ts.end = end_dt
self._ds.add_time_slot(ts)
self._ds.write_update()
def add_time_slot(self, name: str, start_dt: datetime, end_dt: datetime):
self.open_time_slot(name, start_dt)
self.close_time_slot(end_dt)
def update_time_slot(self, old: TimeSlot, new: TimeSlot):
raise NotImplementedError
def delete_time_slot(self, ts: TimeSlot):
raise NotImplementedError
time_slot_container = TimeSlotContainer(DataStore("data.json"))

30
util/parser.py Normal file
View File

@@ -0,0 +1,30 @@
import argparse
def create_parser():
# Create the top-level parser
parser = argparse.ArgumentParser(description="Time tracker.")
subparsers = parser.add_subparsers(dest="command", help="Sub-command help")
# Create the parser for the "ls" command
_ = subparsers.add_parser("ls", help="List all events.")
# Create the parser for the "ps" command
_ = subparsers.add_parser("ps", help="Show the currently running event.")
# Create the parser for the "add" command
parser_add = subparsers.add_parser("add", help="Adding a new event.")
parser_add.add_argument("name", help="Name of the event")
parser_add.add_argument("-s", "--start", required=True, help="Start datetime (default now)")
parser_add.add_argument("-e", "--end", required=True, help="End datetime")
# Create the parser for the "start" command
parser_start = subparsers.add_parser("start", help="Starting a new event.")
parser_start.add_argument("name", help="Name of the event")
parser_start.add_argument("-s", "--start", help="Start datetime (default now)")
# Create the parser for the "end" command
parser_end = subparsers.add_parser("end", help="Ending the current event.")
parser_end.add_argument("-e", "--end", help="End datetime")
return parser

19
util/str_to_datetime.py Normal file
View File

@@ -0,0 +1,19 @@
from datetime import datetime as dt
def datetime(s: str) -> dt:
s = s.strip()
try:
return dt.strptime(s, '%d.%m.%y %H:%M')
except ValueError:
pass
try:
tim = dt.strptime(s, '%H:%M').time()
dat = dt.now().date()
return dt.combine(dat, tim)
except ValueError:
pass
raise ValueError("The given string can not be interpreted as a datetime.")

View File

@@ -1,7 +1,7 @@
from .TimeSlot import TimeSlot
from model.TimeSlot import TimeSlot
def convert_to_table(time_slot_list: list[TimeSlot]):
def convert_to_table(time_slot_list: list[TimeSlot]) -> str:
widths = [30, 26, 26]
r_str = f"+{'-'*(widths[0]+2)}+{'-'*(widths[1]+2)}+{'-'*(widths[2]+2)}+\n"