Doist / todoist-python

DEPRECATED The official Todoist Python API library

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to uncheck a subtree of tasks?

dluxhu opened this issue · comments

Is it possible to query completed subtasks of active tasks somehow? I couldn't figure it out how:

  • api.items does not seem to return them.
  • api.completed.get_all() returns them, but they don't return the full property list (parent_id is missing for example) and it is not possible to filter for parent_id either.

What I'd like to do is to uncheck a whole subtree of tasks given a root task id.

I have written a script that does this. You need to loop through all children one at a time, and uncomplete them.

Any update on this by any chance?

Hey @dluxhu perhaps I can help you out here. As I said, I have already written this functionality using this Todoist Python library. I will paste the function here that does it.

def get_sub_items(self, parent_id):
    sub_items = []
    for tds_item in self.api.state['items']:
        if tds_item['parent_id'] == parent_id:
            sub_items.append(self._tds_item_to_item(tds_item))
    return sub_items

def uncomplete_item(self, item, *, recursively=True):

    # Get the raw item, and complete it
    tds_item = item.tds_item
    
    # Only perform the uncomplete action IF the item is checked
    if tds_item['checked']:
        tds_item.uncomplete()
    
    # If the user wants it, uncomplete the children and attributes as well
    if recursively:
        # Uncomplete all sub-items (if they exist and have been requested above)
        for sub_item in self.get_sub_items(tds_item['id']):
            self.uncomplete_item(sub_item, recursively=True)
    
    return True

My code has some helper functions that translate data, etc., but this should give you an idea.

Lloyd

Hi @dluxhu , you'll notice that I am searching every item to find the sub-items. This means looping over every single Todoist item in my account. Thankfully, Python is fast and I only have perhaps 1000 Todoist items at one time. Even if you have many thousands of Todoist items (what are you doing in Todoist..?), it would still be a quick operation.

As for your questions about caching and stale data. Perhaps I do not understand your use case. You can request a sync of your data 50 times a minute, which is an absurdly high and useful limit for most people. Here is the code I call before I do an operation:

api = TodoistAPI(user_api_token)
api.sync()

After this, all data is synced and correct.

Are you in need of something in addition to that?

Lloyd

I have a Heroku-based Python client that allows me to do special things with Todoist. One of them allows me to uncheck all children of a repeating task, when I complete the repeating task. I have been using this system for around 6 months, and it has not failed me yet. However, out of curiosity, I ran a test to try and replicate your issue.

Test 1

  1. Create a repeating task
  2. Add a subtask
  3. Mark repeating task (parent) complete. This of course does not actually mark the parent as complete, since it is repeating.
  4. (server automatically notices change and runs code)
  5. Child is uncompleted: Success!

Test 2

  1. Create a repeating task
  2. Add a subtask
  3. Restart my Heroku servers (dynos)
  4. Mark repeating task complete
  5. (server automatically notices change and runs code)
  6. Child is left completed: Failure...
  7. Add a new child and complete it
  8. Mark repeating task as complete again
  9. New child is uncompleted (Success!), old child is still left completed (Failure...)

It appears you have identified a bug in my code, and a limitation of the Todoist SyncAPI I was not aware of until right now. It is both frustrating that sync does not include completed tasks (for this exact reason) and a really good thing (for performance reasons).

I may not work on this code for another couple of months, so unfortunately I cannot immediately try to resolve both of our issues here. Have you looked into this to see if there is a way to force-sync completed tasks? I think there is a way based on some documentation I read awhile ago, but I cannot remember it right now.

Lloyd

Hi Lloyd,

What I found in the API is in the first comment of this bug, but it is not adequate.

Balázs