2024-04-12 10:16:03 +00:00
|
|
|
'''
|
|
|
|
just remembered tomatos aren't vegetables. whoops
|
|
|
|
'''
|
2024-04-07 01:30:06 +00:00
|
|
|
import random
|
|
|
|
|
|
|
|
import sqlalchemy as sa
|
|
|
|
|
|
|
|
from co3.schemas import SQLSchema
|
2024-04-12 10:16:03 +00:00
|
|
|
from co3 import CO3, collate, Mapper
|
2024-04-07 01:30:06 +00:00
|
|
|
from co3 import util
|
|
|
|
|
|
|
|
|
|
|
|
class Vegetable(CO3):
|
|
|
|
def __init__(self, name, color):
|
|
|
|
self.name = name
|
|
|
|
self.color = color
|
|
|
|
|
|
|
|
class Tomato(Vegetable):
|
|
|
|
def __init__(self, name, radius):
|
|
|
|
super().__init__(name, 'red')
|
|
|
|
self.radius = radius
|
|
|
|
|
|
|
|
@property
|
|
|
|
def attributes(self):
|
|
|
|
return vars(self)
|
2024-04-12 10:16:03 +00:00
|
|
|
|
|
|
|
def collation_attributes(self, action_key, action_grounp):
|
|
|
|
return {
|
|
|
|
'name': self.name,
|
|
|
|
'state': action_key,
|
|
|
|
}
|
2024-04-07 01:30:06 +00:00
|
|
|
|
|
|
|
@collate('ripe', action_groups=['aging'])
|
|
|
|
def ripen(self):
|
|
|
|
return {
|
|
|
|
'age': random.randint(1, 6)
|
|
|
|
}
|
|
|
|
|
|
|
|
@collate('rotten', action_groups=['aging'])
|
|
|
|
def rot(self):
|
|
|
|
return {
|
|
|
|
'age': random.randint(4, 9)
|
|
|
|
}
|
|
|
|
|
|
|
|
@collate('diced', action_groups=['cooking'])
|
|
|
|
def dice(self):
|
|
|
|
return {
|
|
|
|
'pieces': random.randint(2, 12)
|
|
|
|
}
|
|
|
|
|
2024-04-12 10:16:03 +00:00
|
|
|
type_list = [Vegetable, Tomato]
|
|
|
|
|
2024-04-07 01:30:06 +00:00
|
|
|
'''
|
|
|
|
VEGETABLE
|
|
|
|
|
|
|
|
|
TOMATO -- AGING
|
|
|
|
|
|
|
|
|
-- COOKING
|
2024-04-12 10:16:03 +00:00
|
|
|
|
|
|
|
Note: foreign keys need to represent values that could be known by objects _without_ first interacting
|
|
|
|
with a DB. This is slightly non-standard, given how common it is to depend on another table's integer ID
|
|
|
|
(typically a value assigned by the DB using an autoincrement, for example, and not specified explicitly
|
|
|
|
within the insertion body). As a result, SQLTable components need to be able to operate by another unique
|
|
|
|
key when expected to connect to other tables in the hierarchy. Below we use `name` with a UNIQUE constraint
|
|
|
|
for this purpose. Note that having an integer `id` is still perfectly okay so that a table can manage
|
|
|
|
uniqueness of its own rows by default.
|
2024-04-07 01:30:06 +00:00
|
|
|
'''
|
|
|
|
metadata = sa.MetaData()
|
|
|
|
vegetable_table = sa.Table(
|
|
|
|
'vegetable',
|
|
|
|
metadata,
|
|
|
|
sa.Column('id', sa.Integer, primary_key=True),
|
2024-04-12 10:16:03 +00:00
|
|
|
sa.Column('name', sa.String, unique=True),
|
|
|
|
|
2024-04-07 01:30:06 +00:00
|
|
|
sa.Column('color', sa.String),
|
|
|
|
)
|
|
|
|
tomato_table = sa.Table(
|
|
|
|
'tomato',
|
|
|
|
metadata,
|
|
|
|
sa.Column('id', sa.Integer, primary_key=True),
|
2024-04-12 10:16:03 +00:00
|
|
|
sa.Column('name', sa.String, util.db.deferred_cd_fkey('vegetable.name'), unique=True),
|
|
|
|
|
2024-04-07 01:30:06 +00:00
|
|
|
sa.Column('radius', sa.Integer),
|
|
|
|
)
|
|
|
|
tomato_aging_table = sa.Table(
|
|
|
|
'tomato_aging_states',
|
|
|
|
metadata,
|
|
|
|
sa.Column('id', sa.Integer, primary_key=True),
|
2024-04-12 10:16:03 +00:00
|
|
|
sa.Column('name', sa.String, util.db.deferred_cd_fkey('tomato.name'), unique=True),
|
|
|
|
|
2024-04-07 01:30:06 +00:00
|
|
|
sa.Column('state', sa.String),
|
2024-04-12 10:16:03 +00:00
|
|
|
sa.Column('age', sa.Integer),
|
2024-04-07 01:30:06 +00:00
|
|
|
)
|
|
|
|
tomato_cooking_table = sa.Table(
|
|
|
|
'tomato_cooking_states',
|
|
|
|
metadata,
|
|
|
|
sa.Column('id', sa.Integer, primary_key=True),
|
2024-04-12 10:16:03 +00:00
|
|
|
sa.Column('name', sa.String, util.db.deferred_cd_fkey('tomato.name'), unique=True),
|
|
|
|
|
|
|
|
sa.Column('state', sa.String),
|
2024-04-07 01:30:06 +00:00
|
|
|
sa.Column('pieces', sa.Integer),
|
|
|
|
)
|
2024-04-12 10:16:03 +00:00
|
|
|
vegetable_schema = SQLSchema.from_metadata(metadata)
|
|
|
|
vegetable_mapper = Mapper(vegetable_schema)
|
|
|
|
|
2024-04-13 21:59:43 +00:00
|
|
|
def attr_name_map(cls):
|
|
|
|
return f'{cls.__name__.lower()}'
|
|
|
|
|
|
|
|
def coll_name_map(cls, action_group):
|
|
|
|
return f'{cls.__name__.lower()}_{action_group}_states'
|
|
|
|
|
|
|
|
vegetable_mapper.attach_many(
|
|
|
|
type_list,
|
|
|
|
attr_name_map,
|
|
|
|
coll_name_map,
|
|
|
|
)
|
|
|
|
|
|
|
|
'''
|
|
|
|
new mapping type for Mapper attachment:
|
|
|
|
|
|
|
|
Callable[ [type[CO3], str|None], tuple[str, tuple[str], tuple[str]]]
|
|
|
|
|
|
|
|
tail tuples to associate column names from central table to collation
|
|
|
|
|
|
|
|
this should complete the auto-compose horizontally
|
|
|
|
'''
|
|
|
|
|