Contributing to another repo
Published: 2023-10-02 15:18:04

## Feature Implementation
To begin with, I had a hard time understanding the project and setting it up, just like any other project when we're new to something, but as I kept on reading the `readme.md` over and over again and used the project to generate some files I got hold of it. It was decent code written by the owner and considering its written in python it was much easier to understand and work with this repo. I used a py lib called `tomli` to parse the TOML file. It handles reading and parsing the file. Besides, it also took care of the invalidity of the TOML file through the use of exceptions. The code changes also made use of existing code that was written for command line flags where it already checks whether a path or a directory is valid or whether a file is a txt or md file among other requirements. The purpose was to reuse the code as much as possible so I also converted the dictionary that `tomli` builds to a Namespace class object since `argparse` library converts the command line flags to a Namespace class' object. This helped me reuse the existing logic which checks for the validity of the flags. Documentation was also updated accordingly.

## Problems Faced
`tomli` library parses the content of a TOML file into a dictionary. The existing code used `argparse` library to parse the command line flags. This library parses the flags into a Namespace object. The code that checks the validity of the command line flags was set to work flawlessly when it encountered a Namespace object, and initially after reading and parsing the content of the TOML config file into a dictionary, I used the same code to check the validity of the flags provided by the config file. This didn't end well. If I try to accommodate the condition checking for the dictionary object it'll break the logic for the Namespace object and vice versa. Considering that they both are objects of different classes I assumed that this approach would not work and also need the code to be changed which I'm not supposed to touch. So my best option was to convert the dictionary into a Namespace object and from there, I utilized the existing logic to check the validity of command line-provided flags or config file-provided flags. Initially, I wasn't aware if I could convert a dictionary to a Namespace but after researching on the Internet, I found that it was indeed possible and was a very simple piece of code that does the conversion considering this was Python, everything is simple and straightforward to do in Python HAHA!!!

Besides, I also faced an issue with setting default values for the dictionary-converted Namespace object. The existing code checked for the validity of the command line flags; when the flags were not provided, the `argparse` code was set in a way that it'll hold default values like `None` or some other value like a `Boolean` or `String`. When the config file doesn't hold some of these flags, the code that checked for the validity of these flags would break because it expected at least some value for a key (but the key never existed after reading the config file). Initially, I was clueless on how to fix this but then I realized there's a way to get this fixed. In order to accommodate this, after reading, parsing and converting the TOML file contents to a Namespace object, I ran a loop that added keys with default values to the object for the keys which didn't exist and that solved the problem.

Most of the code changes I made: 
```python
if args.config:
        try:
            with open(args.config, "rb") as f:
                default_values = {
                    'path': None,
                    'output': './tml/examples',
                    'lang': 'en-CA',
                    'version': False
                }

                toml_dict = tomli.load(f)

                # Convert the dict to a Namespace object 
                args = argparse.Namespace(**toml_dict)

                # Set any missing args to their default values
                for key, value in default_values.items():
                    setattr(args, key, getattr(args, key, value))
        except tomli.TOMLDecodeError:
            print(f"Error: {args.config} is not a valid config TOML file.")
            return(-1)
        except FileNotFoundError:
            print(f"Error: {args.config} does not exist.")
            return(-1)
        except IsADirectoryError:
            print(f"Error: {args.config} is a directory. Must provide path to config file.")
            return(-1)
```

## Git Usage
Git usage was quite easy for me to work with this time. I'm getting better at using git nowadays. Besides, at the time of writing this blog post, I never got to work with reviewing and testing PRs via remotes. I did read through it and seems like a pretty good feature which I never knew existed, used to test the code changes made on our repo. Hope to utilize it in future.

## Learning Outcomes
I learnt how to collaborate with others and stay in constant touch with the repo owner to get more information, be it code design decisions or any other issues on navigating through the project, etc.