diff --git a/src/arcaea_offline/database.py b/src/arcaea_offline/database.py index b366e1a..f77612f 100644 --- a/src/arcaea_offline/database.py +++ b/src/arcaea_offline/database.py @@ -1,7 +1,7 @@ from sqlalchemy import Engine, select from sqlalchemy.orm import sessionmaker -from .models.common import * +from .models.config import * from .models.scores import * from .models.songs import * from .singleton import Singleton @@ -37,7 +37,7 @@ class Database(metaclass=Singleton): SongsBase.metadata.create_all(self.engine, checkfirst=checkfirst) ScoresBase.metadata.create_all(self.engine, checkfirst=checkfirst) ScoresViewBase.metadata.create_all(self.engine) - CommonBase.metadata.create_all(self.engine, checkfirst=checkfirst) + ConfigBase.metadata.create_all(self.engine, checkfirst=checkfirst) # insert version property with self.sessionmaker() as session: diff --git a/src/arcaea_offline/models/common.py b/src/arcaea_offline/models/common.py index 85fba75..19880a1 100644 --- a/src/arcaea_offline/models/common.py +++ b/src/arcaea_offline/models/common.py @@ -1,18 +1,32 @@ -from sqlalchemy import TEXT -from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column - -__all__ = [ - "CommonBase", - "Property", -] +from sqlalchemy.orm import DeclarativeBase +from sqlalchemy.orm.exc import DetachedInstanceError -class CommonBase(DeclarativeBase): - pass +class ReprHelper: + def _repr(self, **kwargs) -> str: + """ + Helper for __repr__ + https://stackoverflow.com/a/55749579/16484891 -class Property(CommonBase): - __tablename__ = "property" + CC BY-SA 4.0 + """ + field_strings = [] + at_least_one_attached_attribute = False + for key, field in kwargs.items(): + try: + field_strings.append(f"{key}={field!r}") + except DetachedInstanceError: + field_strings.append(f"{key}=DetachedInstanceError") + else: + at_least_one_attached_attribute = True + if at_least_one_attached_attribute: + return f"<{self.__class__.__name__}({','.join(field_strings)})>" + return f"<{self.__class__.__name__} {id(self)}>" - key: Mapped[str] = mapped_column(TEXT(), primary_key=True) - value: Mapped[str] = mapped_column(TEXT()) + def __repr__(self): + if isinstance(self, DeclarativeBase): + return self._repr( + **{c.key: getattr(self, c.key) for c in self.__table__.columns} + ) + return super().__repr__() diff --git a/src/arcaea_offline/models/config.py b/src/arcaea_offline/models/config.py new file mode 100644 index 0000000..e34fb98 --- /dev/null +++ b/src/arcaea_offline/models/config.py @@ -0,0 +1,20 @@ +from sqlalchemy import TEXT +from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column + +from .common import ReprHelper + +__all__ = [ + "ConfigBase", + "Property", +] + + +class ConfigBase(DeclarativeBase, ReprHelper): + pass + + +class Property(ConfigBase): + __tablename__ = "property" + + key: Mapped[str] = mapped_column(TEXT(), primary_key=True) + value: Mapped[str] = mapped_column(TEXT()) diff --git a/src/arcaea_offline/models/scores.py b/src/arcaea_offline/models/scores.py index 6ac279a..eb5e867 100644 --- a/src/arcaea_offline/models/scores.py +++ b/src/arcaea_offline/models/scores.py @@ -4,6 +4,7 @@ from sqlalchemy import TEXT, case, func, inspect, select from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column from sqlalchemy_utils import create_view +from .common import ReprHelper from .songs import Chart, ChartInfo __all__ = [ @@ -16,7 +17,7 @@ __all__ = [ ] -class ScoresBase(DeclarativeBase): +class ScoresBase(DeclarativeBase, ReprHelper): pass @@ -42,7 +43,7 @@ class Score(ScoresBase): # CC BY-SA 4.0 -class ScoresViewBase(DeclarativeBase): +class ScoresViewBase(DeclarativeBase, ReprHelper): pass diff --git a/src/arcaea_offline/models/songs.py b/src/arcaea_offline/models/songs.py index 29afc59..b45922b 100644 --- a/src/arcaea_offline/models/songs.py +++ b/src/arcaea_offline/models/songs.py @@ -3,6 +3,8 @@ from typing import Optional from sqlalchemy import TEXT, ForeignKey from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column +from .common import ReprHelper + __all__ = [ "SongsBase", "Pack", @@ -15,7 +17,7 @@ __all__ = [ ] -class SongsBase(DeclarativeBase): +class SongsBase(DeclarativeBase, ReprHelper): pass