New support for subtasks#594
Conversation
|
If by cache you mean the cache database, it should be enough to just increment the schema version to force a rebuild. |
e87552a to
b6ee7fa
Compare
Ah thank you, I totally missed it! I rebased my changes to make use of this and to describe it properly in comments and in the documentation. I edited the first comment of the PR to remove the "breaking changes" part since it's not true anymore. |
|
Hey, I just rebased this to the current main for myself and as far as I can see everything works as intended, thanks for that! |
064a26f to
8b78386
Compare
WhyNotHugo
left a comment
There was a problem hiding this comment.
Rebased this applying ruff format on the way.
Looks good, appreciate all the attention to detail.
Mostly minor feedback. There are two things which I think can be improved but can be done separate later (I'd rather keep this PR lean and not block on further changes):
- Tree-building. This seems rather inefficient right now, but I won't block merging on that; we can iterate later gradually.
- Style. I think the output would be easier to parse keeping the left
[ ] $IDfields all aligned, maybe even something like:
[ ] 2 Some task
[ ] 4 ├─ Some subtask
[ ] 3 └─ Another subtask
Again, this seems like something that's best done separately.
| "related_to": "", | ||
| "related_to_reltype": "", |
There was a problem hiding this comment.
We should exclude the fields when absent, instead of including empty fields.
(same applies to other instances below)
| If the database is changed in a breaking way, the ``SCHEMA_VERSION`` variable | ||
| in the class ``Cache`` has to be incremented to allow the cache to be recreated | ||
| after todoman has been updated. An example would be adding new fields or | ||
| removing old unnecessary fields and etc. | ||
|
|
| # Merges all different property arguments into one dictionary | ||
| # `todo_properties` argument, so that it can be directly looped through | ||
| # easily for directly setting the `todoman.model.Todo` class attributes | ||
| # from within a command function. | ||
| # | ||
| # The names of the options are the same as the | ||
| # `todoman.model.Todo` class attributes. | ||
| @functools.wraps(command) | ||
| def command_wrap(*a, **kw) -> click.Command: |
There was a problem hiding this comment.
Nitpick: this should be a docstring rather than comment.
| ) | ||
|
|
||
| _subtask_option = click.option( | ||
| "--subtask-for", |
There was a problem hiding this comment.
What do you think of calling this --parent?
Code-wise it's a bit more obvious, but I'm not sure how obvious it is for a user interface.
| changes = True | ||
| todo.description = sys.stdin.read() | ||
|
|
||
| if subtask_for is not None and not_subtask is False: |
There was a problem hiding this comment.
If subtask_for and not_subtask, we should return an error (invalid arguments).
| # are specified." | ||
| # Source: | ||
| # https://www.rfc-editor.org/rfc/rfc9253#section-9.1 | ||
| if todo.related_to != "": |
There was a problem hiding this comment.
Check truthiness, so this also matches if it's None.
| if todo.related_to != "": | |
| if todo.related_to: |
| return self._join_tree(tree).strip() | ||
|
|
||
| def _tree_reorder_related( | ||
| self, tree: dict[str, list], related_todos: dict[str, list] |
There was a problem hiding this comment.
Formatting:
| self, tree: dict[str, list], related_todos: dict[str, list] | |
| self, | |
| tree: dict[str, list], | |
| related_todos: dict[str, list], |
| store_path: list = [] | ||
| for related, related_to in related_todos.items(): | ||
| # Find the root parent todo of the `related_to` todo. | ||
| related_to_path_tracer: str = related_to[0] | ||
| related_dict: dict[str, list] = tree | ||
| while related_to_path_tracer in related_todos: | ||
| related_to_path_tracer = related_todos[related_to_path_tracer][0] | ||
| store_path.append(related_to_path_tracer) | ||
|
|
||
| # Walk from the parent root todo, down to the | ||
| # `related_to` todo itself. | ||
| store_path.reverse() | ||
| # If `related_to` is a SIBLING, walk one todo backwards towards the | ||
| # root parent todo. If there is no path to be walked, | ||
| # just ignore it. | ||
| with contextlib.suppress(IndexError): | ||
| if related_to[1] == "SIBLING": | ||
| related_to[0] = store_path.pop() | ||
| for inwards in store_path: | ||
| try: | ||
| related_dict = related_dict[inwards][1] | ||
| if related_dict is None: | ||
| break | ||
| except KeyError: | ||
| related_dict = tree | ||
| break | ||
|
|
||
| self._tree_move_related(related, related_to[0], tree, related_dict) |
There was a problem hiding this comment.
This looks quite inefficient, since it walks the entire list multiple times. I think we need a "real" tree when building the whole tree in the first place.
But this is non-blocking at this stage; we can merge it in its current form and iterate on this later.
| self.related_to = "" | ||
| self.related_to_reltype = "" |
There was a problem hiding this comment.
Default should be None, not empty string. This affects the field's presence in the output icalendar file.
| got_related_to_reltype = "" | ||
| got_related_to = todo.get("related-to", "") | ||
| if got_related_to != "": | ||
| got_related_to_reltype = got_related_to.params.get("reltype") | ||
|
|
There was a problem hiding this comment.
As above, default should be None.
8b78386 to
d52e187
Compare
Taken from RFC 5545, section `3.8.4.5`. If present in a file, these values are now read and stored in the cache. Nothing in the UI has been changed. Tests are modified to reflect the change. Increment `SCHEMA_VERSION` to allow cache recreation on todoman update.
New names and values added to the JSON output for the `RELATED-TO` property.
List text output is now with a tree structure:
task 1
task 2
task 3
task 4
task 5
The table list is changed to a dictionary representing a tree.
No changes to the SQL queries are made.
RELTYPEs PARENT, CHILD and SIBLING are supported.
https://www.rfc-editor.org/rfc/rfc5545#section-3.2.15
Includes output space formatting fixes.
Tests adjusted to changes.
Comment for describing the weird code for merging arguments.
Using the newly supported attributes, two new options are added. `--subtask-for`, making a task be a subtask for another and `--not-subtask`, making a task no longer be a subtask. The commands `new` and `edit` are fitted with these new options.
d52e187 to
373cdee
Compare
Add support for RELATED-TO property and RELTYPE parameter.
Taken from RFC 5545, section
3.8.4.5. If present in a file, these values are now read and stored in the cache.Tests are modified to reflect the change.
The
SCHEMA_VERSIONis incremented to allow the cache to be recreated after the update.Nothing is required from the user to be done for the changes in this PR to work.
Before:

After:

Closes: #396