diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..e7ad219 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +include data/template.csv \ No newline at end of file diff --git a/ToDoList/ToDo.py b/ToDoList/ToDo.py index bdfbdaf..db339d7 100644 --- a/ToDoList/ToDo.py +++ b/ToDoList/ToDo.py @@ -1,56 +1,141 @@ """ A simple ToDo list """ +import pandas as pd +from pathlib import Path -# TODO: -# - read csv -# - write task -# - add a task -# - finish task and remove -# - print tasks +class ToDo: + """ + Driver class for the functionality of the ToDo list. + """ + def __init__(self): + + self.data_file = self.get_path() + self.df = pd.read_csv(self.data_file, sep=",") + self.output_data(self.df) -""" -Function for parsing the input file + def get_path(self): + base_path = Path(__file__).parent + file_path = (base_path / "../data/template.csv").resolve() + return file_path -Parameters ----------- -input file: str + def output_data(self, df): + """ + Prints the DataFrame in the terminal. -Returns -------- -dict - ``task`` (str): name of the tasks - ``status`` (int): status if the task is finished or not + Parameters + ---------- + input file: DataFrame -""" + Returns + ------- + None + """ + data_out = df.copy() + if data_out.empty: + print("There are no tasks.\n") + else: + print("Your tasks:\n") + data_out.loc[(data_out["STATUS"] == 0), ["STATUS"]] = "[ ]" + data_out.loc[(data_out["STATUS"] == 1), ["STATUS"]] = "[X]" + data_out.index = data_out.index + 1 + print(data_out) + return None + + + def add_task(self): + """ + Adds a task to the end of the csv file. + + Parameters + ---------- + None + + Returns + ------- + If no user input is given: + self.output_data(self.df): func + Function to display the updated DataFrame. + + Else: + csv_mod: CSV + Updated CSV file. + self.output_data(df_mod): func + Function to display the updated DataFrame. + """ + new_task = input("Add a new task:\n") + if new_task == "": + print("Wrong input!") + return self.output_data(self.df) + else: + df_mod = self.df.append({"STATUS": 0, "TASK": new_task}, ignore_index=True) + csv_mod = df_mod.to_csv(self.data_file, index=False) + return csv_mod, self.output_data(df_mod) + + + def finish_task(self, chosen_task): + """ + Labels a task as finished. + + Parameters + ---------- + chosen_task: dict of {str: str} + The chosen task which will be labelled as finished. + + Returns + ------- + csv_mod: CSV + Updated CSV file. + self.output_data(df_TTF): func + Function to display the updated DataFrame. + """ + df_TTF = self.df + df_TTF.loc[df_TTF["TASK"] == chosen_task, ["STATUS"]] = 1 + csv_mod = df_TTF.to_csv(self.data_file, index=False) + return csv_mod, self.output_data(df_TTF) -# TODO dict richtig zurückgeben -def read_data(data_file): - with open(data_file) as f: - f.readline() - data = {} - for line in f: - (data["status"], data["task"]) = line.split(";") - # print(f"Your current tasks: \n{input_data}") - print(data) - # return data + def unfinish_task(self, chosen_task): + """ + Labels a task as unfinished. + Parameters + ---------- + chosen_task: dict of {str: str} + The chosen task which will be labelled as unfinished. -def add_task(data_file): - with open(data_file, "a") as f: - new_task = input("Add a new task: \n") - new_task_to_append = f"\n[ ] {new_task}" - f.write(new_task_to_append) + Returns + ------- + csv_mod: CSV + Updated CSV file. + self.output_data(df_TTU): func + Function to display the updated DataFrame. + """ + df_TTU = self.df + df_TTU.loc[df_TTU["TASK"] == chosen_task, ["STATUS"]] = 0 + csv_mod = df_TTU.to_csv(self.data_file, index=False) + return csv_mod, self.output_data(df_TTU) -def main(): - test = "../data/template.csv" - read_data(test) - # add_task(test) - # read_data(test) + def remove_task(self, chosen_task): + """ + Removes a task from the ToDo list. + Parameters + ---------- + chosen_task: dict of {str: str} + The chosen task which will be removed. -if __name__ == "__main__": - main() + Returns + ------- + csv_mod: CSV + Updated CSV file. + self.output_data(new_df_TTR): func + Function to display the updated DataFrame. + """ + df_TTR = self.df + df_TTR = df_TTR.drop(df_TTR[df_TTR["TASK"] == chosen_task].index) + new_df_TTR = df_TTR.reset_index(drop=True) + csv_mod = new_df_TTR.to_csv(self.data_file, index=False) + return csv_mod, self.output_data(new_df_TTR) \ No newline at end of file diff --git a/ToDoList/__init__.py b/ToDoList/__init__.py new file mode 100644 index 0000000..bec5a59 --- /dev/null +++ b/ToDoList/__init__.py @@ -0,0 +1,8 @@ +import os +import ToDoList + +src = os.path.join(os.path.dirname(ToDoList.__file__), 'data/template.csv') + +def get(): + with open(src) as f: + return f.read().strip() \ No newline at end of file diff --git a/ToDoList/cli.py b/ToDoList/cli.py index e69de29..da410d1 100644 --- a/ToDoList/cli.py +++ b/ToDoList/cli.py @@ -0,0 +1,175 @@ +# -*- coding: utf-8 -*- +""" +simple cli for the ToDo list +""" + +from PyInquirer import style_from_dict, prompt +from examples import custom_style_2, custom_style_1 +from .ToDo import ToDo +import pandas as pd + +# TODO: +# manchmal bricht es einfach ab? +# docstrings hinzufügen +# windows support +# tests hinzufügen + + +def ask_operation(liste): + print("\n") + if liste.df.empty: + operation_prompt = { + 'type': 'list', + 'name': 'operation', + 'message': 'What do you want to do?', + 'choices': ['add task', 'exit'] + } + else: + operation_prompt = { + 'type': 'list', + 'name': 'operation', + 'message': 'What do you want to do?', + 'choices': ['add task', 'finish task', 'unfinish task', 'remove task', 'exit'] + } + answers = prompt(operation_prompt, style=custom_style_2) + return answers['operation'] + +def ask_task(series): + tasks = [ + { + 'type': 'list', # raw list geht nur bis 9 --> zu list gewechselt + 'name': 'tasks', + 'message': 'Choose a task!', + 'choices': series + } + ] + tasks = prompt(tasks, style=custom_style_2) + return tasks["tasks"] + +def ask_permission(): + questions = { + 'type': 'confirm', + 'message': 'Do you really want to remove that task?', + 'name': 'continue', + 'default': True + } + answers = prompt(questions, style=custom_style_1) + return answers + + + + +def parse_answer(liste): + """ + + """ + operation = ask_operation(liste) + switch_case = { + 'add task' : c_add_task, + 'finish task' : c_finish_task, + 'unfinish task' : c_unfinished_task, + 'remove task' : c_remove_task, + 'exit' : exit + } + + func = switch_case.get(operation) + func(liste) + +def c_add_task(liste): + """ + Calls the add_task method of liste. + Parameters + ---------- + liste: ToDo() + Instance of the ToDo class. + + Returns + ------- + parse_answer(liste): func + """ + liste.add_task() + liste.df = pd.read_csv(liste.data_file, sep=",") + return parse_answer(liste) + +def c_finish_task(liste): + relevant_tasks = liste.df.loc[(liste.df["STATUS"] == 0)] + series = relevant_tasks["TASK"].tolist() + if len(series) == 0: + print("No unfinished tasks available!\n") + return parse_answer(liste) + else: + chosen_task = ask_task(series) + liste.finish_task(chosen_task) + return parse_answer(liste) + +def c_unfinished_task(liste): + relevant_tasks = liste.df.loc[(liste.df["STATUS"] == 1)] + series = relevant_tasks["TASK"].tolist() + if len(series) == 0: + print("No finished tasks available!\n") + return parse_answer(liste) + else: + chosen_task = ask_task(series) + liste.unfinish_task(chosen_task) + return parse_answer(liste) + +def c_remove_task(liste): + series = liste.df["TASK"].tolist() + chosen_task = ask_task(series) + row = liste.df.loc[(liste.df["TASK"] == chosen_task)] + status = row["STATUS"].values + if (status[0] == 0): + permission = ask_permission() + if permission["continue"] == True: + liste.remove_task(chosen_task) + liste.df = pd.read_csv(liste.data_file, sep=",") + return parse_answer(liste) + else: + liste.output_data(liste.df) + return parse_answer(liste) + else: + liste.remove_task(chosen_task) + liste.df = pd.read_csv(liste.data_file, sep=",") + return parse_answer(liste) + +def greeting(): + """Greets the user of the command line interface.""" + return r""" + ______ ____ __ __ +/\__ _\ /\ _`\ /\ \ __ /\ \__ +\/_/\ \/ ___\ \ \/\ \ ___\ \ \ /\_\ ____\ \ ,_\ + \ \ \ / __`\ \ \ \ \ / __`\ \ \ __\/\ \ /',__\\ \ \/ + \ \ \/\ \L\ \ \ \_\ \/\ \L\ \ \ \L\ \\ \ \/\__, `\\ \ \_ + \ \_\ \____/\ \____/\ \____/\ \____/ \ \_\/\____/ \ \__\ + \/_/\/___/ \/___/ \/___/ \/___/ \/_/\/___/ \/__/ + + Brought to you by @pipaj97 and @hugo_weizenkeim + """ + +def exit(liste): + """ + Enables not to change the ToDo list. + + Parameters + ---------- + liste: ToDo() + Instance of the ToDo class. + + Returns + ------- + raw str + """ + return r""" +༼ つ ◕_◕ ༽つ Don't leave me alone! ༼ つ ◕_◕ ༽つ + """ + + +def main(): + print(greeting()) + liste = ToDo() + parse_answer(liste) + print(exit(liste)) + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/data/template.csv b/data/template.csv index 7cfba1e..a4068c3 100644 --- a/data/template.csv +++ b/data/template.csv @@ -1,4 +1,2 @@ -status;task -[ ];this is a test -[ ];fsu fsiufg sfisvb -[ ];gewdf +STATUS,TASK +1,test1 diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..dc67bd5 --- /dev/null +++ b/setup.py @@ -0,0 +1,31 @@ +import sys +from setuptools import setup, find_packages + +setup( + # Self-descriptive entries which should always be present + name="ToDoList", + author="pipaj97", + author_email="julian.pipart@fu-berlin.de", + # Which Python importable modules should be included when your package is installed + # Handled automatically by setuptools. Use 'exclude' to prevent some specific + # subpackage(s) from being added, if needed + packages=find_packages(), + # package_data={"" : ["template.csv"]}, + # Optional include package data to ship with your package + # Customize MANIFEST.in if the general case does not suit your needs + # Comment out this line to prevent the files from being packaged with your software + include_package_data=True, + # Entry point + entry_points={"console_scripts": ["ToDo = ToDoList.cli:main"]}, + # Allows `setup.py test` to work correctly with pytest + # Additional entries you may want simply uncomment the lines you want and fill in the data + # url='http://www.my_package.com', # Website + # install_requires=[], # Required packages, pulls from pip if needed; do not use for Conda deployment + # platforms=['Linux', + # 'Mac OS-X', + # 'Unix', + # 'Windows'], # Valid platforms your code works on, adjust to your flavor + # python_requires=">=3.5", # Python version restrictions + # Manual control if final package is compressible or not, set False to prevent the .egg from being made + # zip_safe=False, +) \ No newline at end of file