Locked learning resources

Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Locked learning resources

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Initializing the To-Do Database

00:00 In the last lesson, you wrote the code for setting up the application configuration file. In this lesson, you’ll write the code for initializing, the to-do database.

00:10 To do that, you open your database.py module. The first thing to do is to import the needed libraries. You can import configparser because you’ve been needing that to read your database configuration settings and also from pathlib import Path.

00:27 You’ll also need this module for path manipulation and just as you had before from the rp_todo package, you’d import some error codes, DBWriter, and success code.

00:39 Now even though the intended function of your application is that users initialize the application, giving it a path to the database, which is the path to the JSON file as a fail set, you can also give it a default DB file path to be used if the user doesn’t specify any JSON file location path.

00:57 And for this, you store the value into a variable called default_db_file_path. And the value of that variable would be using the pathlib module, get the path of the current file, which is the database.py module, and then step two directories up with .parent.parent to get to the root project directory, and then use the .joinpath() method to create a file called .default_todo.json.

01:27 This is to enable storing the database also in the root project directory. Again, if users don’t provide a database location, this is the default JSON file to be used as the database.

01:41 Now, the next function you try to create is one that actually gets the database path read from your application’s configuration file. To define this function, you’d call it get_database_path.

01:53 And as an argument, you’d expect a config_file type annotated to receive a variable of type Path and what you’d expect as a return value will be of type Path.

02:05 You can add a little docstring to describe what this function does.

02:11 Next, you instantiate your configparser with config_parser = configparser .ConfigParser().

02:21 Now that you have a configparser instance,

02:25 use the .read() method and then you pass in the config_file.

02:30 And if all goes well, it would read the config file, parse it, get the database path and return it to the caller of this function.

02:42 This function will return a path to the application’s database. Next is to create a main database initializer function, def init_database().

02:54 What this accepts will be db_path type annotated to specify that it’s of a type Path and the return value will be an integer, which is the operation’s execution response code.

03:06 Also as good practice, you can have a docstring for this and you say create the to-do database. In the try and except block, you’ll try and the database initialization, and if an error occurs, return a DB_WRITE_ERROR.

03:22 And in the try block, the operation you expect to carry out is db_path. Being a pathlib Path object, you have a method called .write_text().

03:32 And to this, you pass the value in strings an empty list. As a comment you can just say that this initializes an empty to-do list,

03:43 and if this goes as planned, you’d return a success code.

03:49 Now you have a way to retrieve your database file path on the application’s configuration file. And after that, be able to initialize the database given that path.

03:59 The next thing to do is to get a Typer init CLI command that will carry out this operation of initializing the configuration settings, reading the database path from either the user entry or the default path, and then creating this database initialized with an empty list.

04:16 To do that, you can go back to your cli.py module.

04:20 In here is where you’ll create the init CLI command. First, you’ll import a few additional libraries from pathlib import Path,

04:31 and then you’ll import a few more things from rp_ todo package, you get the config module and the database module.

04:40 Now just above the version callback function, right below the Typer app instance, define an init function. But as you have seen with Typer, to create a command out of this function, you simply need to add the app.command decorator, which now makes this function a Typer CLI command.

05:00 Using type annotation, you specify that this function will have a return value of None, and then you add a little docstring here to enhance what Typer comes up with for the application documentation.

05:13 This initializes the to-do database, and here you’re going to need one parameter passed to this function and that is the db_path, and you’d expect this to come from the user and you would annotate this db_path to become a Typer option.

05:30 And to do that using Typer’s extensions annotated,

05:35 you specify that you expect a string value, and some more information about this string value is that it is a type of Typer option

05:45 and some flags that will be used to access this value is --db-path, or another option in quotes -db. And because you want this value to come from the user when this command is written, you can ask for that value using Typer’s prompt, say prompt, and then a description of this prompt, which is what you’re asking for.

06:12 In this case, I have the to-do database location as the description of my prompt.

06:18 And if this value is not given, you can set the default value to be string format off from the database module import default_db_file_path. That is database.default_db _file_path.

06:36 Now you have the definition of the init command. Next is to go into the function itself to define and code up the main operations. And the first thing you do is initialize the application itself.

06:48 And to do that as it defined in the app config, you can say from the config module, call the function init_app(), pass in db_path,

06:59 and you can assign the response of this function call to a variable called app_init_error.

07:08 After receiving the db_path from the user, you call the init_app() function to initialize the application’s database. Next thing you do, you check if this app_init_error exists.

07:22 If it’s success, it’s going to be zero, but if it’s not, it’s going to be one of the other response codes from one to six. So if it’s not zero, what you would like to do is echo all to the console that something has gone wrong.

07:34 And for that, you’d use Typer. Now instead of echo, you can use another method called secho. And this just allows you to add a little style to the printout in the console.

07:48 And as a value, you’d have using f-string the message saying, Creating config file failed with. Now you’re letting the user know that an error has occurred trying to create a config file.

08:03 And to get the actual error, you’d use the errors dictionary, and with the app_init_error code, you’d access the human-readable descriptive message for that error.

08:14 One of the cool features of Typer’s secho is that you can style this text a little further, and for this you can try to make this a red color showing an error or danger.

08:24 And for that you can use typer.colors.RED, and this will use a red printout in the console. And if this happens, what you want is to exit the operation at this point.

08:37 And for that, you’d use raise typer.Exit(), and you can pass the code one. But if the config file was initialized successfully, the next thing is to try to initialize your application’s database. To do that, using a similar method, from the database module you call the init_database() function, and pass to that a Path instance because you receive a string value of db_path and record that in a variable called db_init_error.

09:10 And in the same vein, you can copy this check and paste that underneath the db_init() function. But you can now instead you check if there’s a db_init_ error using Typer’s secho, say `Creating database failed with` and from the error dictionary, you’ll access the human-readable error description message, printing that out in the console in red text, and then exiting the operation at that point.

09:42 But if the db_init_error is zero, meaning the success code, then what you do is using Typer’s secho notify users that a database has been created with an f-string the to-do database is the path passed by the user, and this can be styled with green text using fg=typer.colors.GREEN.

10:05 Great. You’ve just completed the first Typer CLI command, which is the init command, whose function is to initialize your application’s configuration and database.

10:19 To test this out, you can head over to your terminal to check that this application command has been recorded, save all files. To test this out in your terminal, you can run python3 -m rp_ todo --help, and you should now see the init command present in your CLI application.

10:40 And to take this command for a spin also in your terminal, you can run python3 -m rp_todo and pass the init command. And this will now ask for the database location since you specify that the application prompts user to enter the location for the to-do database. First, you can use the default value set and with M three nothing and just pressing Enter that should use the default location, which is the root project directory, and in the file called default_todo.json.

11:17 And if you look in your project’s root directory, you should see a JSON file titled default_todo.json. And if you check also, there should be a file config .ini also created in your project’s root directory, showing that your application has initialized the configuration file and the to-do database.

11:37 Looking at the configuration file, you’d see that the database path has been written to the config .ini file. To test user-entered values first, I can just go ahead to delete the default database

11:55 and try the process again.

11:58 This time, instead of accepting the default value, I can specify a path to my project root directory.

12:06 Then after getting the path to my project root directory, I specify a file called .rp_

12:14 todo.json,

12:17 and this should use the user-entered path as the path to the application database. This can be confirmed by looking into the config.ini file.

12:26 Great. You’ve just successfully initialized your to-do application’s configuration and also initialized the application database. Next, you’re going to set up your application’s backend and connect it with this database.

Become a Member to join the conversation.