Marking an Item Done
00:00
In the previous lessons, you’ve developed and added the typer
add
00:05
and list command to your CLI application. In this lesson, the next feature you’ll be working on is the Typer set_done
command. A command that allows users to mark a to-do item as done.
00:18
This way, users can track how much work they’ve achieved and items left to be completed. And in the usual fashion, the first thing will be to code up the set_done
method in your to-do or utility class.
00:31
This method will take a to-do item’s ID and mark it as done in the database by setting the done Boolean value to True
. First things first, you create a method and you call it set_done
.
00:45
This is a class method. First, you reference .self
and then the only parameter that this method takes is a todo_id
and you type annotate this to specify that it’s going to be an integer value and the response will be via a typer
current to-do.
01:00 And as is good practice, you can add some docstring.
01:04 So because you’re working with a file system, the general strategy would be you read all the to-do items into a list, you identify the to-do item you’re trying to update, and after updating that, you then write back a new updated list to the database.
01:18
And to code that up, first you read all the to-do items from the database using the database handler and calling the read_todos
method, assigning this value to a variable called read
. Again, this will return a DB response that will contain a to-do list and an error or response code.
01:38 Next, you just check if that operation was successful by checking if there is a read error.
01:45
If it was successful, this will be zero and this will be false. But if not, you’ll have one of the error codes from one to six. And if so, you can return an instance of CurrentTodo
with an empty to-do item dictionary and pass back the error code to the caller of this method.
02:04
Next, you try to identify the to-do items to be updated. And for that, you try to identify an item from a given list. You can use a try and except block. Seeing that you’re trying to access an item from a list, the possible error that could occur would be an IndexError
.
02:21
And if that happens, you just return an instance of Current
Todo
with an empty dictionary object and call an ID_ERROR
.
02:30
If this doesn’t exist, remember to import it from rp
todo
. Great. Now to access the to-do item itself using the todo_id
, you can identify the item from the to-do list todo = read
the to-do list and passing the index.
02:50 Now because Python is zero-indexed, the first item in your list will start from index 0, 1, 2, 3, and so on. So whatever index is given, you can assume that the actual to-do item value would be at index minus one position.
03:06
Now that you’ve obtained the to-do at the intended index, to update the status, you’re going to do a list update in place. So you identify the to-do, which you know is a dictionary, and get the key Done
and update it to True
.
03:21 This will update the value of that to-do item in the list in place. And after that is done, the next thing to do is to write back this new updated list to the database.
03:31
And to write the data back into the database, you can call .self._db_handler
, the very helpful utility class, and call the write_todos
method and pass in the new updated to-do list.
03:45
And you can assign the response of this operation to a variable called write
. And if this is successful or not, you return an instance of current to-do with the to-do you just updated and the status of the operation.
04:01
Because you know the write_todos
will return an instance of DB response, which contains a list of to-dos and the response code. So you use that response code here.
04:11
With all this in place, it’s time to go ahead to implement a CLI Typer set_done
command. Remember to save the file and head over to cli.py
module and right under the list_all
command, you’re going to create a new command and call that set_done
. Again, to ensure that this is a typer
CLI command, you decorate this function using @app.command()
and because this is kind of a long name for a command, you can use an alias, say name="complete"
.
04:44
So this will be the command to run the set_done
function.
04:48
This will return no value, so you can annotate that to specify the return value will be None
. So you can add a little docstring again to enhance the documentation provided by typer
: `Complete to-do by setting it as done using the to-do ID`.
05:05
If you just put pass
, then go ahead over to the terminal to confirm that this command has been registered. As usual, in your terminal, if you run python3 -m rp
todo --help
.
05:18
You should now see that the complete command has indeed been registered to your CLI application. Great. Now you can implement the actual functionality. So the first thing you do is tackle the parameters needed for this command. And the unique parameter this command will need is the todo_id
.
05:34
And using typer
extensions Annotated
, add more metadata to this. First, specify that this parameter will be of type int
and this integer will be a typer.Argument
.
05:46
And using ellipsis, specify to typer
that this argument is absolutely required and the command will fail if not passed. And then you can add some help text. If you save this and head back to your terminal, the reason for this help text is so for each of the arguments you have in your typer
CLI application, you can check the help documentation.
06:09 And you should see the help text here giving users more information about the arguments and description of the command.
06:18 Now back to the command implementation. The first thing you need to do is get the todoer class. This is the utility class that facilitates communication between the CLI application and the database.
06:29
And to get an instance of that, you have a function already that gets you an instance of that todoer class, the get_todoer()
. You use that function, assign to a variable called todoer
.
06:40
Now with this function, you’re now able to call the set_done
method, which has been defined in the todoer class. So you say todo.set_done(
pass the todo_id
argument.
06:54 When you assign the response of this operation to two variables because you expect an instance of the current to-do and an error or response code, then you proceed to check if the operation was successful.
07:06
If error
, that is, if this is non-zero and anything from one to six, then it means an error occurred and you can let the user know using typer.secho(
say something like `Completing to-do with a todo_id failed with`.
07:20 Now you give the user a descriptive error and to get the descriptive error message, call your errors dictionary and pass in the error code.
07:27 Also, as this is an error, you can style this with a red text.
07:32
Now at this point, you can exit the operation by raising typer
.Exit()
, exit code one. But if the operation is successful, in the else block, you can let the user know that the operation has been carried out.
07:47
Also using typer.secho(
by saying to-do with the ID get a description, it’s now completed.
07:56 And as this is an expected operation, you can have a green text for that.
08:02
Now you have the CLI command to set a to-do item as Done
. You’re going to give that a try by heading over to your terminal. First, you can view all the to-do items you have in your database again, by saying python3 -m rptodo_list
.
08:18
In my case here, I have three to-do items, all with a done status of False
. What if I wanted to update the to-do item with ID two, which is wash my car?
08:28
For that, you can type python3 -m rptodo
complete
with the ID two.
08:36
And that should set that to-do item as completed. To confirm, you can list the to-do items again and you should now see that that to-do item has been set to completed with the Done
status set to True
.
08:49
You’ve just completed the feature to mark a to-do item as Done
. Next, you work on the feature to remove to-do items from the database.
Become a Member to join the conversation.