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

Preparing and Configuring a Database

00:00 In the previous lessons, you’ve put together a type of CLI application for your to-do project,

00:06 created an entry point script, and ran the application for the first time. The next step is to define how your application will initialize and connect to the to-do database.

00:18 For this project, you’ll use JSON files to store the data about your to-dos. JSON, which stands for JavaScript Object Notation, is a lightweight human-readable format for storing and transferring data.

00:31 Some benefits of working with JSON include: it’s clear and readable, it’s language independent, it has a structured format, and it’s portable.

00:44 Now what you do is start to write code for creating, connecting, and initializing your to-do database so that it’s ready for use. The very first step will be to define how your application will find the database in your file system.

00:58 And for that, you need some configuration setup. You can easily just pass the file path to your JSON file as strings in your application each time the application runs.

01:08 But a much better approach is to define a configuration setting that allows for proper code and application management. And for this, you set up a to-do app configuration file in a directory of choice to store the path to the database and then use pathlib to work with the file system and then configparser to handle the configuration file.

01:31 And both these packages are available for you to use in the standard Python library. To begin, open your config.py module in the rp_ todo package. First, you’ll import the libraries you need, which is import configparser from the Python standard library.

01:48 And then from pathlib, import Path, and of course, you import typer.

01:56 Now you would import some of the previously set up things from rptodo package. You’ll import some of the error code that you have defined and then the application name variable. DB_READ_ERROR, DB_ WRITE_ERROR, DIRECTORY_ERROR, FILE_ERROR, SUCCESS, and then the __app_name__.

02:16 Next, you define a config directory path. This is where your application will store the configuration files and settings. You have full control over this and can decide where you’d like to store this, but for the sake of this project, you can use the current root project directory as the path to store your config file.

02:33 And to do that, you’d use the pathlib module assigned to a variable called CONFIG_DIR_PATH. You’d assign the value an instance of Path

02:46 to get the path of the current module. So you call Path() and in brackets you’d add __ file__, and you’d use that to access the root parent project directory by going two directories up, so the parent of the current module, which is the rptodo package, and then the parent of that, which is the root project directory.

03:10 Next, you’ll define the path to the actual configuration file. And to do this, you’ll assign to a variable called CONFIG_FILE_PATH,

03:18 the value using CONFIG_DIR_PATH defined above forward slash and the name of the config file itself, which would just be config.ini.

03:28 You’ll be using an INI file to store the configurations and this config.ini file will be your application’s configuration file.

03:36 Next is to define some helper functions to handle the initialization of your application’s configuration and also the initialization of your database config settings.

03:47 The first helper function you define is the init_ config_file() function. And you can type annotate this to specify that it returns an integer value, which will be one of the operations response code.

03:59 In Python, using underscore in front of function or variable names is used to specify that these functions or variables are internal functions and variables or internal objects.

04:10 And what that means is that these helper functions will most likely never be used outside this module. So you define the _init_ config_file() function.

04:21 This function takes no argument and in it you have a try and except block. An expected error will be an OSError. That is if something goes wrong when trying to run a path manipulation operation, and if this occurs, you’d return a DIRECTORY_ERROR code.

04:37 But if all things go well in the try block, what you expect is that the CONFIG_DIR_PATH you specified is created if it doesn’t exist, using CONFIG_DIR_PATH, being a Path object .mkdir() method.

04:52 And then you specify to pathlib that it’s okay if this directory already exists.

04:58 So this operation right here will try to create your CONFIG_DIR_PATH. If something goes wrong, you’re going to have a response code returned. After the CONFIG_DIR_PATH has been created, the next step is to try to create the actual configuration file and you’ll use a similar process so you can copy the code above and paste right below.

05:19 Now, instead of the CONFIG_DIR_PATH, what you’ll have is the CONFIG_FILE_PATH. And this time you’re not making a directory but rather creating a file.

05:28 So you’d use the .touch() method and also specify to pathlib that it’s okay if this file already exists. And if something goes wrong during that process, you’d return a FILE_ERROR.

05:41 But if all goes well, you just return SUCCESS, which is just code zero. You’ve just created your first helper function, which is to initialize the configuration file.

05:52 Next, you create another helper function to help create and initialize your database. And to do that, you’ll have def create_database().

06:04 This will take db_path as an argument where you type annotate to specify that it’s going to be a string. Then also for type annotation, specify that the return value would be of data type integer to represent the operation execution response code.

06:19 First, you initialize an instance of the ConfigParser.

06:26 Then what you want is to create a section to put the configuration settings for your database. And to do so, you create a general section this way just as you would create a new Python dictionary key.

06:39 And the key value should be general. And to this, you’ll assign a dictionary with key database and value db_path, which is the string value representing the path to the JSON file.

06:52 You’ve initialized the ConfigParser and also set a configuration setting, but this hasn’t yet been written to the configuration file and you’re going to try to do that next.

07:02 For this, you’re up in the try and catch block.

07:08 This is a file or path operation so you catch an OSError if something goes wrong, and if so, return a DB_WRITE_ERROR. And if everything goes as planned, you just return SUCCESS code, which is just integer zero.

07:23 Now in the main try block, you’re going to try using context management provided by the with statement to handle file operation, say with CONFIG_FILE_PATH .open() in write mode as file.

07:39 And in the context block config_parser.write(file). This will write the ConfigParser settings into the config file. And with that, you’ve just created the database helper function, which you’re going to be using shortly.

07:55 Now with these two helper functions completed, you’re going to go ahead to create your main initialization function def init_app(). This is going to expect a db_path type annotated as string and a return value that will be of data type integer, which is the operation’s execution or response code.

08:19 You can add some docstrings to your function: """ Initializes the application. """. Then the first thing you need to do is the config file initialization.

08:30 For this, you’ll call the config file helper function

08:34 and assign the response to a variable called config_code. Then you check if the operation was successful by checking if the config_code is SUCCESS.

08:46 If it’s not equal to SUCCESS, then you return the code,

08:50 but if it is, it means you can proceed and that the application’s configuration file has been created. You can proceed to initialize your database configuration.

09:01 Also using the same method, you’d call the create_ database() helper function. And to that, you’d pass in a db_path

09:10 and assign the response of this operation to a variable called database_code.

09:18 Then you check if that operation was successful by saying, if database_code is not equal to SUCCESS, meaning something must have gone wrong, then you return that database_code.

09:30 But if all things go well, you just return the SUCCESS code. Great. You’ve now just defined all the code required to initialize your application’s configuration settings, and also initialize your application’s database configuration.

09:45 With this, you’ve written the code for setting up the application’s configuration file to store the path to your application’s database. Next, is to write the code for initializing the database itself and getting it ready for use.

Become a Member to join the conversation.