Utilizing Metaprogramming in Python

1.25 hours
  • 2 Learning Objectives

About this Hands-on Lab

Metaprogramming is not often something that we need to use, but when we do it is there. If avoidable, it is probably recommended to not rely on metaprogramming because it is hard for other programmers to understand. In this hands-on lab, we’ll be building a metaclass to make it easy to create database models. By the time you’ve finished this lab, you’ll have demonstrated a good grasp of how to create a metaclass and a common way to use metaprogramming.

Learning Objectives

Successfully complete this lab by achieving the following learning objectives:

Create ModelClass Metaclass and Add a Dynamic Initializer

Create a subclass of the type class and implement the __new__ method. From here, create and attach an initializer based on the annotations on the class.

Build and Attach get_by_xxx Class Methods for Each Attribute on the Model

For each of the annotations on the class build a get_by_xxx method and attack it as a class method.

Additional Resources

Your team is considering writing their own object relational mapper, and they've asked you to start by creating an easy way for them to create a class and have it automatically have "getter" class methods to search the database based on properties. Utilizing annotations for fields, they'd like to have class methods like get_by_name added to the class if there was a class annotation for name: str. Here is an example:

class Post(metaclass=ModelClass):
    # if not defined, it would default to `post`.
    # For a multi-word class it would default to all lowercase, snake_cases
    # Eg. BlogPost would default to blog_post table.
    __tablename__ = "posts"

    title: str
    content: str
    published: bool

posts_query = Post.get_by_title("Example")
posts_query == "select * from posts where title = 'Example'"

new_post = Post("New Title", "This is my content", False)

To achieve this, we'll need to have the metaclass create an initializer based on the annotations and also add get_by_xxx methods based on these same annotations. Because we're not working with an actual database yet, we're just going to have these functions return the query. This query will generally follow the same patterns:

select * from [__tablename__] where [field_name] = value

There are a lot of things to consider when creating an ORM, but your job is to work on creating a good model metaclass to make creating a new model incredibly easy.

There are some automated tests for this process. You can run all of the unit tests with the following command:

$ python -m unittest
...
----------------------------------------------------------------------
Ran 3 tests in 0.004s

OK

What are Hands-on Labs

Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.

Sign In
Welcome Back!

Psst…this one if you’ve been moved to ACG!

Get Started
Who’s going to be learning?