import dataclasses
import inspect
from dataclasses import dataclass, field
from pprint import pprint

import attr


class ManualComment:
    def __init__(self, id: int, text: str):
        self.id: int = id
        self.text: str = text

    def __repr__(self):
        return "{}(id={}, text={})".format(self.__class__.__name__, self.id, self.text)

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

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

    def __hash__(self):
        return hash((self.__class__, self.id, self.text))

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

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

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

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


@dataclass(frozen=True, order=True)
class Comment:
    id: int
    text: str = ""
    replies: list[int] = field(default_factory=list, repr=False, compare=False)


@attr.s(frozen=True, order=True, slots=True)
class AttrComment:
    id: int = 0
    text: str = ""


def main():
    comment = Comment(1, "I just subscribed!")
    # comment.id = 3  # can't immutable
    print(comment)
    print(dataclasses.astuple(comment))
    print(dataclasses.asdict(comment))
    copy = dataclasses.replace(comment, id=3)
    print(copy)

    pprint(inspect.getmembers(Comment, inspect.isfunction))


if __name__ == '__main__':
    main()

[((58, 1, 58, 35), 'dataclasses.dataclass', 'dataclass', (), '', False, 'from dataclasses import dataclass, field\n'), ((65, 1, 65, 44), 'attr.s', 'attr.s', (), '', False, 'import attr\n'), ((62, 25, 62, 79), 'dataclasses.field', 'field', (), '', False, 'from dataclasses import dataclass, field\n'), ((77, 11, 77, 45), 'dataclasses.replace', 'dataclasses.replace', (), '', False, 'import dataclasses\n'), ((75, 10, 75, 38), 'dataclasses.astuple', 'dataclasses.astuple', ({(75, 30, 75, 37): 'comment'}, {}), '(comment)', False, 'import dataclasses\n'), ((76, 10, 76, 37), 'dataclasses.asdict', 'dataclasses.asdict', ({(76, 29, 76, 36): 'comment'}, {}), '(comment)', False, 'import dataclasses\n'), ((80, 11, 80, 58), 'inspect.getmembers', 'inspect.getmembers', ({(80, 30, 80, 37): 'Comment', (80, 39, 80, 57): 'inspect.isfunction'}, {}), '(Comment, inspect.isfunction)', False, 'import inspect\n')]