Hone logo
Hone
Problems

Custom Attribute Validation with Metaclasses

Metaclasses in Python provide a powerful mechanism for controlling class creation. This challenge asks you to implement a metaclass that automatically validates attributes defined within a class, ensuring they meet specific criteria (in this case, that they are strings). This is useful for enforcing data consistency and preventing errors early in the development process.

Problem Description

You are tasked with creating a metaclass called StringAttributeValidator. This metaclass should intercept the class creation process and modify the class definition to ensure that all attributes defined within the class are strings. Specifically, the metaclass should:

  1. Intercept Class Creation: The metaclass should be invoked during class creation.
  2. Validate Attributes: For each attribute defined in the class, check if its value is a string.
  3. Raise TypeError: If any attribute is not a string, raise a TypeError with a descriptive message indicating the offending attribute and its incorrect type.
  4. Return the Modified Class: The metaclass should return the modified class object after validation.

The class definition should be able to handle both class-level attributes defined directly within the class body and attributes defined using assignment statements within the class body.

Examples

Example 1:

class ValidClass(metaclass=StringAttributeValidator):
    name = "Alice"
    age = "30"
    city = "New York"

Output: No error is raised. The class ValidClass is successfully created.

Explanation: All attributes (name, age, city) are strings, so the validation passes.

Example 2:

class InvalidClass(metaclass=StringAttributeValidator):
    name = "Bob"
    age = 25  # Integer, not a string
    city = "London"

Output:

TypeError: Attribute 'age' must be a string.  Found <class 'int'> instead.

Explanation: The attribute age is an integer, violating the string-only requirement. The metaclass raises a TypeError.

Example 3:

class AnotherInvalidClass(metaclass=StringAttributeValidator):
    name = "Charlie"

    def __init__(self, age):
        self.age = age # This will not be caught by the metaclass

    city = "Paris"

Output: No error is raised. The metaclass only validates attributes defined directly in the class body, not those assigned within methods like __init__.

Constraints

  • The metaclass must be implemented using the __new__ method.
  • The validation should only apply to attributes defined directly within the class body (not attributes assigned within methods like __init__).
  • The TypeError message should clearly indicate the attribute name and the incorrect type found.
  • The code should be well-documented and easy to understand.

Notes

  • Remember that metaclasses are invoked before the class body is executed.
  • The __dict__ attribute of a class stores its attributes. You can use this to inspect and modify the attributes.
  • Consider how to handle different attribute types gracefully. The problem specifically asks for string validation, but think about how you might extend this to other validation rules.
  • The __new__ method is responsible for creating the class object. It receives the class name, base classes, and attributes as arguments. It must return the class object.
class StringAttributeValidator(type):
    def __new__(cls, name, bases, attrs):
        for attr_name, attr_value in attrs.items():
            if not isinstance(attr_value, str):
                raise TypeError(f"Attribute '{attr_name}' must be a string.  Found {type(attr_value)} instead.")
        return super().__new__(cls, name, bases, attrs)
Loading editor...
python