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:
parent
e768dae978
commit
ada7812e3b
5 changed files with 47 additions and 50 deletions
|
@ -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}"
|
||||
|
|
|
@ -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}"
|
||||
|
|
17
todo/Task.py
17
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 = ""
|
||||
|
|
38
todo/Todo.py
38
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()
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue