Skip to content

[Feature request] Add utility to print source of attrs class. #1472

@ShaiAvr

Description

@ShaiAvr

I love this library. It lets me write classes without writing boilerplate that would take a lot of time. However, I am a very curious person, and I'd like to know what code attrs generated for my class. It can be useful to both debug unexpected behaviour and to get a feel for all the boilerplate attrs handles for me. In the docs there is an example that if I write:

@attrs.define
class SmartClass:
    a = attrs.field()
    b = attrs.field()

it will roughly be translated into:

class ArtisanalClass:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def __repr__(self):
        return f"ArtisanalClass(a={self.a}, b={self.b})"

    def __eq__(self, other):
        if other.__class__ is self.__class__:
            return (self.a, self.b) == (other.a, other.b)
        else:
            return NotImplemented

    def __ne__(self, other):
        result = self.__eq__(other)
        if result is NotImplemented:
            return NotImplemented
        else:
            return not result

    def __lt__(self, other):
        if other.__class__ is self.__class__:
            return (self.a, self.b) < (other.a, other.b)
        else:
            return NotImplemented

    def __le__(self, other):
        if other.__class__ is self.__class__:
            return (self.a, self.b) <= (other.a, other.b)
        else:
            return NotImplemented

    def __gt__(self, other):
        if other.__class__ is self.__class__:
            return (self.a, self.b) > (other.a, other.b)
        else:
            return NotImplemented

    def __ge__(self, other):
        if other.__class__ is self.__class__:
            return (self.a, self.b) >= (other.a, other.b)
        else:
            return NotImplemented

    def __hash__(self):
        return hash((self.__class__, self.a, self.b))

First of all, this example is weird since the class name has changed, and also, there are comparison methods despite the fact that order=True wasn't given. Also, __slots__ are missing. Ignoring, these issues it would still be nice to see the code generated by attrs.

I tried to write a simple class:

@attrs.define
class SmartClass:
    a: int
    b: str = "default"

    def __repr__(self) -> str:
        return f"<SmartClass(a={self.a})>"

and I tried to inspect its code using inspect.getsource:

import inspect

print(inspect.getsource(SmartClass))

However, I just got the original class definition without any attrs generated methods. The docs show that inspect.getsource can retrieve the generated code for individual methods. However, I would also like to be able to see the entire generated code with a regular class syntax. I think a utility function should be added to return the entire generated source code, so it can be inspected.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions