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
This commit is contained in:
riley 2021-09-25 23:25:30 -04:00
parent e768dae978
commit ada7812e3b
5 changed files with 47 additions and 50 deletions

View file

@ -1,25 +1,21 @@
from __future__ import annotations from __future__ import annotations
from .Task import Task
from .TodoObject import TodoObject from .TodoObject import TodoObject
class Category(TodoObject): class Category(TodoObject):
def __init__(self, name : str, level: int, parent = None): def __init__(self, name : str, level: int, parent = None):
super().__init__(level, name, parent) super().__init__(level, name, parent)
def get_subcategories(self) -> list[Category]: def get_notes(self, immediate = True):
categories = [] from .Note import Note
for child in self.children: return self.get_children(immediate, Note)
if isinstance(child, Category):
categories.append(child)
return categories
def get_tasks(self) -> list[Task]: def get_subcategories(self, immediate = True):
tasks = [] return self.get_children(immediate, Category)
for child in self.children:
if isinstance(child, Task): def get_tasks(self, immediate = True):
tasks.append(child) from .Task import Task
return tasks return self.get_children(immediate, Task)
def __str__(self): def __str__(self):
return "#"*(self.level+1) + f" {self.text}" return "#"*(self.level+1) + f" {self.text}"

View file

@ -7,6 +7,13 @@ class Note(TodoObject):
self.listed = listed self.listed = listed
super().__init__(level, text, parent) 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): def __str__(self):
if self.listed: if self.listed:
return f"- {self.text}" return f"- {self.text}"

View file

@ -3,7 +3,6 @@ from __future__ import annotations
from typing import Union from typing import Union
from datetime import datetime from datetime import datetime
from .Note import Note
from .TodoObject import TodoObject from .TodoObject import TodoObject
class Task(TodoObject): class Task(TodoObject):
@ -12,18 +11,12 @@ class Task(TodoObject):
self.complete = complete self.complete = complete
super().__init__(level, name, parent) super().__init__(level, name, parent)
def get_subtasks(self) -> list[Task]: def get_subtasks(self, immediate = True):
tasks = [] return self.get_children(immediate, Task)
for child in self.children:
if isinstance(child, Task):
tasks.append(child)
return tasks
def get_notes(self): def get_notes(self, immediate = True):
notes = [] from .Note import Note
for child in self.children: return self.get_children(immediate, Note)
if isinstance(child, Note):
notes.append(child)
def __str__(self): def __str__(self):
output = "" output = ""

View file

@ -4,7 +4,7 @@ import logging
from pathlib import Path from pathlib import Path
from datetime import datetime from datetime import datetime
from typing import Optional from typing import Optional, Type
from .TodoObject import TodoObject from .TodoObject import TodoObject
from .Category import Category from .Category import Category
@ -57,23 +57,27 @@ class Todo(TodoObject):
else: # catch-all for unlisted notes else: # catch-all for unlisted notes
return 0 return 0
def _get_parent(self, level, object: TodoObject): def _get_parent(self, level, obj: TodoObject, obj_type: Type[TodoObject] = None):
"""Gets the parent of an object at level X. """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: Args:
level (int): The level to find the parent for. 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: Returns:
TodoObject: The object found. TodoObject: The object found.
""" """
if level > 0: if level > 0:
for child in object.children[::-1]: for child in obj.children[::-1]:
if child.level < level: if obj_type is not None and isinstance(child, obj_type) and child.level < level:
return child return child
return object if obj_type is None and child.level < level:
return child
return obj
else: else:
return object return obj
def _parse_note(self, line: str, parent: TodoObject): def _parse_note(self, line: str, parent: TodoObject):
"""Parses a markdown line representing a note. """Parses a markdown line representing a note.
@ -119,7 +123,7 @@ class Todo(TodoObject):
line (str): The line to parse. line (str): The line to parse.
""" """
level = self._get_level(line) level = self._get_level(line)
parent = self._get_parent(level, self) parent = self._get_parent(level, self, obj_type=Category)
line = line[level+2:] line = line[level+2:]
Category(line, level, parent) Category(line, level, parent)
@ -134,9 +138,9 @@ class Todo(TodoObject):
elif line[0] == "#": elif line[0] == "#":
self._parse_category(line) self._parse_category(line)
elif re.match(" *- \\[[x ]\\]", 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: 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: def get_md(self, category_spacing: int = 1) -> str:
"""Gets the markdown text of the current data loaded into the object. """Gets the markdown text of the current data loaded into the object.
@ -168,14 +172,6 @@ class Todo(TodoObject):
Returns: Returns:
Optional[Category]: Returns the category if found. Optional[Category]: Returns the category if found.
""" """
for i in self.children: for i in self.get_children(obj_type=Category):
if isinstance(i, Category) and i.text == name: if i.text == name:
return i return i
def main():
"""Generates a markdown of my todos"""
todo = Todo()
print(todo)
if __name__ == "__main__":
main()

View file

@ -1,6 +1,7 @@
from __future__ import annotations
import logging import logging
from typing import Optional from typing import Optional, Type
logger = logging.getLogger("TodoObject") logger = logging.getLogger("TodoObject")
logger.setLevel(logging.INFO) logger.setLevel(logging.INFO)
@ -16,12 +17,16 @@ class TodoObject:
if parent is not None: if parent is not None:
self.set_parents(parent) self.set_parents(parent)
def get_children(self, immediate = False): def get_children(self, immediate = False, obj_type: Type[TodoObject] = None) -> list[TodoObject]:
output = [] output = []
for child in self.children: 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) 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) output.append(child)
return output return output