From ada7812e3b2fed4ffaf7543578e6b74d5e7361f9 Mon Sep 17 00:00:00 2001 From: riley Date: Sat, 25 Sep 2021 23:25:30 -0400 Subject: [PATCH] Parent/Child assignment & fetching refactor - TodoObject.get_children accepts an obj_type to filter by - Todo._get_parent accepts an obj_type to filter potential parents - Todo._parse_category now properly assigns parent categories - Reworked get_* methods in Task, Category, and Note to use get_children --- todo/Category.py | 22 +++++++++------------- todo/Note.py | 7 +++++++ todo/Task.py | 17 +++++------------ todo/Todo.py | 38 +++++++++++++++++--------------------- todo/TodoObject.py | 13 +++++++++---- 5 files changed, 47 insertions(+), 50 deletions(-) diff --git a/todo/Category.py b/todo/Category.py index 4d9f294..3d65e6b 100644 --- a/todo/Category.py +++ b/todo/Category.py @@ -1,25 +1,21 @@ from __future__ import annotations -from .Task import Task from .TodoObject import TodoObject class Category(TodoObject): def __init__(self, name : str, level: int, parent = None): super().__init__(level, name, parent) - def get_subcategories(self) -> list[Category]: - categories = [] - for child in self.children: - if isinstance(child, Category): - categories.append(child) - return categories + def get_notes(self, immediate = True): + from .Note import Note + return self.get_children(immediate, Note) - def get_tasks(self) -> list[Task]: - tasks = [] - for child in self.children: - if isinstance(child, Task): - tasks.append(child) - return tasks + def get_subcategories(self, immediate = True): + return self.get_children(immediate, Category) + + def get_tasks(self, immediate = True): + from .Task import Task + return self.get_children(immediate, Task) def __str__(self): return "#"*(self.level+1) + f" {self.text}" diff --git a/todo/Note.py b/todo/Note.py index d7e0b1c..f47660e 100644 --- a/todo/Note.py +++ b/todo/Note.py @@ -7,6 +7,13 @@ class Note(TodoObject): self.listed = listed super().__init__(level, text, parent) + def get_subnotes(self, immediate = True): + return self.get_children(immediate, Note) + + def get_tasks(self, immediate = True): + from .Task import Task + return self.get_children(immediate, Task) + def __str__(self): if self.listed: return f"- {self.text}" diff --git a/todo/Task.py b/todo/Task.py index 7f15c14..e6e7d87 100644 --- a/todo/Task.py +++ b/todo/Task.py @@ -3,7 +3,6 @@ from __future__ import annotations from typing import Union from datetime import datetime -from .Note import Note from .TodoObject import TodoObject class Task(TodoObject): @@ -12,18 +11,12 @@ class Task(TodoObject): self.complete = complete super().__init__(level, name, parent) - def get_subtasks(self) -> list[Task]: - tasks = [] - for child in self.children: - if isinstance(child, Task): - tasks.append(child) - return tasks + def get_subtasks(self, immediate = True): + return self.get_children(immediate, Task) - def get_notes(self): - notes = [] - for child in self.children: - if isinstance(child, Note): - notes.append(child) + def get_notes(self, immediate = True): + from .Note import Note + return self.get_children(immediate, Note) def __str__(self): output = "" diff --git a/todo/Todo.py b/todo/Todo.py index 1ab6272..feaf599 100644 --- a/todo/Todo.py +++ b/todo/Todo.py @@ -4,7 +4,7 @@ import logging from pathlib import Path from datetime import datetime -from typing import Optional +from typing import Optional, Type from .TodoObject import TodoObject from .Category import Category @@ -57,23 +57,27 @@ class Todo(TodoObject): else: # catch-all for unlisted notes return 0 - def _get_parent(self, level, object: TodoObject): - """Gets the parent of an object at level X. + def _get_parent(self, level, obj: TodoObject, obj_type: Type[TodoObject] = None): + """Gets the parent for an object at level X. + If an object with a lower level cannot be found within the obj, it will return the obj. Args: level (int): The level to find the parent for. - object (TodoObject): Object to grab parents from. + obj (TodoObject): Object to grab parents from. + obj_type (Type[TodoObject]): The type of the object the parent should be. Default is None. Returns: TodoObject: The object found. """ if level > 0: - for child in object.children[::-1]: - if child.level < level: + for child in obj.children[::-1]: + if obj_type is not None and isinstance(child, obj_type) and child.level < level: return child - return object + if obj_type is None and child.level < level: + return child + return obj else: - return object + return obj def _parse_note(self, line: str, parent: TodoObject): """Parses a markdown line representing a note. @@ -119,7 +123,7 @@ class Todo(TodoObject): line (str): The line to parse. """ level = self._get_level(line) - parent = self._get_parent(level, self) + parent = self._get_parent(level, self, obj_type=Category) line = line[level+2:] Category(line, level, parent) @@ -134,9 +138,9 @@ class Todo(TodoObject): elif line[0] == "#": self._parse_category(line) elif re.match(" *- \\[[x ]\\]", line): - self._parse_task(line, self.children[-1]) + self._parse_task(line, self.get_children(obj_type=Category)[-1]) else: - self._parse_note(line, self.children[-1]) + self._parse_note(line, self.get_children(obj_type=Category)[-1]) def get_md(self, category_spacing: int = 1) -> str: """Gets the markdown text of the current data loaded into the object. @@ -168,14 +172,6 @@ class Todo(TodoObject): Returns: Optional[Category]: Returns the category if found. """ - for i in self.children: - if isinstance(i, Category) and i.text == name: + for i in self.get_children(obj_type=Category): + if i.text == name: return i - -def main(): - """Generates a markdown of my todos""" - todo = Todo() - print(todo) - -if __name__ == "__main__": - main() diff --git a/todo/TodoObject.py b/todo/TodoObject.py index b541067..a6fbe1d 100644 --- a/todo/TodoObject.py +++ b/todo/TodoObject.py @@ -1,6 +1,7 @@ +from __future__ import annotations import logging -from typing import Optional +from typing import Optional, Type logger = logging.getLogger("TodoObject") logger.setLevel(logging.INFO) @@ -16,12 +17,16 @@ class TodoObject: if parent is not None: self.set_parents(parent) - def get_children(self, immediate = False): + def get_children(self, immediate = False, obj_type: Type[TodoObject] = None) -> list[TodoObject]: output = [] for child in self.children: - if immediate and child.parent is self: + if obj_type is not None and isinstance(child, obj_type) and immediate and child.parent is self: output.append(child) - elif not immediate: + elif obj_type is None and immediate and child.parent is self: + output.append(child) + elif obj_type is not None and isinstance(child, obj_type) and not immediate: + output.append(child) + elif obj_type is None and not immediate: output.append(child) return output