Skip to content

TypeError using doit forget with no default tasks specified #478

@hwswdude

Description

@hwswdude

Executing doit run does build all tasks if no default_tasks are specified.
Executing doit forget throws an exception if no default_tasks are specified.

I can try to create a pull request. Would be my first.

How to fail

Use (any) dodo.py without default_tasks`

Steps

  • Execute doit run -> all tasks get build
  • Execute doit forget -> get NoneType exception. I'm expecting: a) forgets all tasks or b) forget every task
  • Execute doit forget --all -> forgets all tasks
(.venv) :~/doit_bug/test$ doit
.  test
(.venv) :~/doit_bug/test$ doit
-- test
(.venv) :~/doit_bug/test$ doit forget
Traceback (most recent call last):
  File "~/doit_bug/.venv/lib/python3.14/site-packages/doit/doit_cmd.py", line 294, in run
    return command.parse_execute(args)
           ~~~~~~~~~~~~~~~~~~~~~^^^^^^
  File "~/doit_bug/.venv/lib/python3.14/site-packages/doit/cmd_base.py", line 150, in parse_execute
    return self.execute(params, args)
           ~~~~~~~~~~~~^^^^^^^^^^^^^^
  File "~/doit_bug/.venv/lib/python3.14/site-packages/doit/cmd_base.py", line 570, in execute
    return self._execute(**exec_params)
           ~~~~~~~~~~~~~^^^^^^^^^^^^^^^
  File "~/doit_bug/.venv/lib/python3.14/site-packages/doit/cmd_forget.py", line 62, in _execute
    for name in forget_list:
                ^^^^^^^^^^^
TypeError: 'NoneType' object is not iterable
(.venv) :~/doit_bug/test$ doit forget --all
forgetting all tasks
(.venv) :~/doit_bug/test$ doit
.  test

What I found

class Forget(DoitCmdBase):
    doc_purpose = "clear successful run status from internal DB"
    doc_usage = "[TASK ...]"
    doc_description = None

    cmd_options = (opt_forget_taskdep, opt_disable_default, opt_forget_all)

def _execute(self, forget_sub, forget_disable_default, forget_all):
        """remove saved data successful runs from DB
        """
## Does not handle special case: self.sel_tasks is None
## Could execute forget_all if self.sel_default_tasks and not forget_disable_default
        if forget_all:
            self.dep_manager.remove_all()
            self.outstream.write("forgetting all tasks\n")
## Does not care about empty default_tasks->
        elif self.sel_default_tasks and forget_disable_default:
            self.outstream.write(
                "no tasks specified, pass task name, --enable-default or --all\n")

        # forget tasks from list
        else:
            tasks = dict([(t.name, t) for t in self.task_list])
## check_tasks_exist() returns instead of throwing an error message like
## "no tasks specified, pass task name or --all\n")
            check_tasks_exist(tasks, self.sel_tasks)
            forget_list = self.sel_tasks

            if forget_sub:
                to_forget = list(tasks_and_deps_iter(tasks, forget_list, True))
            else:
                to_forget = []
                for name in forget_list:
                    task = tasks[name]
                    to_forget.append(task)
                    to_forget.extend(subtasks_iter(tasks, task))
## Fails as to_forget has never had a value other than initialized to None
            for task in to_forget:
                # forget it - remove from dependency file
                self.dep_manager.remove(task.name)
                self.outstream.write("forgetting %s\n" % task.name)
        self.dep_manager.close()

Environment

  1. OS: Ubuntu
  2. python version: Python3.14
  3. doit version: 0.36.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions