import re
from typing import Any

from sqlalchemy.orm import as_declarative, declared_attr


@as_declarative()
class Base:
    id: Any
    __name__: str

    # Generate __tablename__ automatically
    @declared_attr
    def __tablename__(cls) -> str:
        name = cls.__name__
        # It is a regex that matches CamelCase and replaces it with snake_case
        # https://stackoverflow.com/questions/1175208/elegant-python-function-to-convert-camelcase-to-snake-case
        return re.sub(r'(?<!^)(?=[A-Z])', '_', name).lower()

    # required in order to access columns with server defaults or SQL expression
    # defaults, subsequent to a flush, without triggering an expired load
    __mapper_args__ = {'eager_defaults': True}
