Missed the last update as I was on summer vacation; I should have planned to start this week instead.
This week my focus has largely been on the bookshelf
project. It has been tough but also rewarding to get to where I am, and I feel like I’m learning at the edge of my abilities. I far overestimated that I would be done by now, but it’s been good progress just putting in the time to learn.
I started by learning a lot about Typer and how it works as the CLI tool of choice.
I implemented a skeleton cli.py
with all the commands I plan on adding so that I can see with bookshelf --help
what the interface looks like. Most of the work has been creating data models for the Book
and Review
classes, and setting up a database.
Below is the demo of the app with the bookshelf add
command in action. Inspired by libro - a command-line book tracking tool
Not sure what I’ll show in next weeks demo, but I hope to have a few more commands implemented. I’d be very happy if I can get to importing some data directly from Goodreads, which will involve working on a custom parser.
Some things I learned this week
Learning Typer at first by going through the tutorial, but found it more helpful to sketch out what I wanted and then ask an LLM for specific things as I needed them.
A review of classes in Python and using dataclasses to build the Book
and Review
data models. A good refresher on class methods, static methods, and using the typing module to enforce type hints. It was really nice to finally use dataclasses for a non-trivial project.
Working with SQLite, which was a highlight. One of my joys has been exploring information stored in SQLite databases e.g. book info from my ereader; bookmarks, history from web browser, messages from iMessage… This was my first time creating one myself, and it was delightful. Already thinking of mother projects to take on after. Some notes to self for the future:
conn.row_factory = sqlite3.Row
to access columns by name instead of index- using context managers instead of manually closing connections, and using
json
to store tags in the database as a list of strings - ALWAYS use parameterized queries with
?
placeholders and pass values as a tuple. Using f-strings or concatenation with user input is unsafe and makes the app vulnerable to SQL injection.
with get_db_connection() as conn:
book_dict = self.to_dict()
# convert tags to a json string
book_dict["tags"] = json.dumps(book_dict["tags"])
cursor = conn.execute(
"""
INSERT INTO books (title, author, tags)
VALUES (?, ?, ?)""",
tuple(book_dict.values()),
)
book_id = cursor.lastrowid
conn.commit()
Other updates this week
- Worked on 3 Exercisms: Difference of Squares, ETL, and Flatten Array. The last one was quite challenging since I didn’t think of using recursion at all.
- Made it through the Recursion and Quick Sort chapters of Grokking Algorithms. I need to spend more time on exercises here to make sure it sticks before I move on; especially to develop an intuition around choosing base cases.