100 lines
2.6 KiB
Python
100 lines
2.6 KiB
Python
import enum
|
|
|
|
import nanoid
|
|
from nanoid_dictionary import human_alphabet
|
|
from slugify import slugify
|
|
from sqlalchemy import Column, String, inspect
|
|
from sqlalchemy.orm import DeclarativeBase, MappedAsDataclass
|
|
|
|
|
|
def genslug():
|
|
return nanoid.generate(human_alphabet[2:], 5)
|
|
|
|
|
|
class SlugMixin:
|
|
slug = Column(String, index=True, unique=True, default=genslug)
|
|
|
|
@property
|
|
def uri(self):
|
|
return "-".join([self.slug, slugify(self.name.title().replace(" ", ""), ok="", only_ascii=True, lower=False)])
|
|
|
|
|
|
class BaseObject(MappedAsDataclass, DeclarativeBase):
|
|
"""
|
|
Allows for iterating over Model objects' column names and values
|
|
"""
|
|
|
|
__abstract__ = True
|
|
|
|
def __iter__(self):
|
|
values = vars(self)
|
|
for attr in self.__mapper__.columns.keys():
|
|
if attr in values:
|
|
yield attr, values[attr]
|
|
for relname in self.__mapper__.relationships.keys():
|
|
relvals = []
|
|
reliter = self.__getattribute__(relname)
|
|
if not reliter:
|
|
yield relname, relvals
|
|
continue
|
|
for rel in reliter:
|
|
try:
|
|
relvals.append({k: v for k, v in vars(rel).items() if not k.startswith("_")})
|
|
except TypeError:
|
|
relvals.append(rel)
|
|
yield relname, relvals
|
|
|
|
def __json__(self):
|
|
"""
|
|
Provide a custom JSON encoder.
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
def __repr__(self):
|
|
return str(dict(self))
|
|
|
|
def copy(self):
|
|
self_as_dict = dict(self.__dict__)
|
|
self_as_dict.pop("_sa_instance_state")
|
|
mapper = inspect(self).mapper
|
|
for primary_key in mapper.primary_key:
|
|
self_as_dict.pop(primary_key.name)
|
|
for key in mapper.relationships.keys():
|
|
if key in self_as_dict:
|
|
self_as_dict.pop(key)
|
|
return self.__class__(**self_as_dict)
|
|
|
|
|
|
class EnumField(enum.Enum):
|
|
"""
|
|
A serializable enum.
|
|
"""
|
|
|
|
def __json__(self):
|
|
return self.value
|
|
|
|
|
|
STATS = ["strength", "dexterity", "constitution", "intelligence", "wisdom", "charisma"]
|
|
|
|
CREATURE_TYPES = [
|
|
"aberation",
|
|
"beast",
|
|
"celestial",
|
|
"construct",
|
|
"dragon",
|
|
"elemental",
|
|
"fey",
|
|
"fiend",
|
|
"Giant",
|
|
"humanoid",
|
|
"monstrosity",
|
|
"ooze",
|
|
"plant",
|
|
"undead",
|
|
]
|
|
SIZES = ["Tiny", "Small", "Medium", "Large", "Huge", "Gargantuan"]
|
|
|
|
CreatureTypesEnum = EnumField("CreatureTypesEnum", ((k, k) for k in CREATURE_TYPES))
|
|
StatsEnum = EnumField("StatsEnum", ((k, k) for k in STATS))
|
|
SizesEnum = EnumField("SizesEnum", ((k, k) for k in SIZES))
|