Metadata list

This commit is contained in:
Gregoo 2025-01-30 16:23:47 +01:00
parent cd70fb28dc
commit 23a1e2efbd
8 changed files with 99 additions and 65 deletions

View File

@ -0,0 +1,77 @@
import logging
from typing import Type
from .exceptions import NotFoundException
from .fields import BrickRecordFields
from .record_list import BrickRecordList
from .set_status import BrickSetStatus
logger = logging.getLogger(__name__)
T = BrickSetStatus
# Lego sets metadata list
class BrickMetadataList(BrickRecordList[T]):
kind: str
mapping: dict[str, T]
model: Type[T]
# Database table
table: str
# Queries
select_query: str
def __init__(self, model: Type[T], /, *, force: bool = False):
# Load statuses only if there is none already loaded
records = getattr(self, 'records', None)
if records is None or force:
# Don't use super()__init__ as it would mask class variables
self.fields = BrickRecordFields()
logger.info('Loading {kind} list'.format(
kind=self.kind
))
self.__class__.records = []
self.__class__.mapping = {}
# Load the statuses from the database
for record in self.select():
status = model(record=record)
self.__class__.records.append(status)
self.__class__.mapping[status.fields.id] = status
# Return the items as columns for a select
def as_columns(self, /, **kwargs) -> str:
return ', '.join([
'"{table}"."{column}"'.format(
table=self.table,
column=record.as_column(),
)
for record
in self.filter(**kwargs)
])
# Filter the list of records (this one does nothing)
def filter(self) -> list[T]:
return self.records
# Grab a specific status
def get(self, id: str, /) -> T:
if id not in self.mapping:
raise NotFoundException(
'{kind} with ID {id} was not found in the database'.format(
kind=self.kind.capitalize(),
id=id,
),
)
return self.mapping[id]
# Get the list of statuses depending on the context
def list(self, /, **kwargs) -> list[T]:
return self.filter(**kwargs)

View File

@ -1,5 +1,6 @@
from .instructions_list import BrickInstructionsList from .instructions_list import BrickInstructionsList
from .retired_list import BrickRetiredList from .retired_list import BrickRetiredList
from .set_status import BrickSetStatus
from .set_status_list import BrickSetStatusList from .set_status_list import BrickSetStatusList
from .theme_list import BrickThemeList from .theme_list import BrickThemeList
@ -12,7 +13,7 @@ def reload() -> None:
BrickInstructionsList(force=True) BrickInstructionsList(force=True)
# Reload the set statuses # Reload the set statuses
BrickSetStatusList(force=True) BrickSetStatusList(BrickSetStatus, force=True)
# Reload retired sets # Reload retired sets
BrickRetiredList(force=True) BrickRetiredList(force=True)

View File

@ -9,6 +9,7 @@ from .exceptions import NotFoundException
from .minifigure_list import BrickMinifigureList from .minifigure_list import BrickMinifigureList
from .part_list import BrickPartList from .part_list import BrickPartList
from .rebrickable_set import RebrickableSet from .rebrickable_set import RebrickableSet
from .set_status import BrickSetStatus
from .set_status_list import BrickSetStatusList from .set_status_list import BrickSetStatusList
from .sql import BrickSQL from .sql import BrickSQL
if TYPE_CHECKING: if TYPE_CHECKING:
@ -161,7 +162,7 @@ class BrickSet(RebrickableSet):
# Load from database # Load from database
if not self.select( if not self.select(
statuses=BrickSetStatusList().as_columns(solo=True) statuses=BrickSetStatusList(BrickSetStatus).as_columns(all=True)
): ):
raise NotFoundException( raise NotFoundException(
'Set with ID {id} was not found in the database'.format( 'Set with ID {id} was not found in the database'.format(

View File

@ -3,6 +3,7 @@ from typing import Self
from flask import current_app from flask import current_app
from .record_list import BrickRecordList from .record_list import BrickRecordList
from .set_status import BrickSetStatus
from .set_status_list import BrickSetStatusList from .set_status_list import BrickSetStatusList
from .set import BrickSet from .set import BrickSet
@ -37,7 +38,7 @@ class BrickSetList(BrickRecordList[BrickSet]):
# Load the sets from the database # Load the sets from the database
for record in self.select( for record in self.select(
order=self.order, order=self.order,
statuses=BrickSetStatusList().as_columns() statuses=BrickSetStatusList(BrickSetStatus).as_columns()
): ):
brickset = BrickSet(record=record) brickset = BrickSet(record=record)
@ -73,7 +74,7 @@ class BrickSetList(BrickRecordList[BrickSet]):
for record in self.select( for record in self.select(
order=order, order=order,
limit=limit, limit=limit,
statuses=BrickSetStatusList().as_columns() statuses=BrickSetStatusList(BrickSetStatus).as_columns()
): ):
brickset = BrickSet(record=record) brickset = BrickSet(record=record)

View File

@ -1,71 +1,23 @@
import logging import logging
from .exceptions import NotFoundException from .metadata_list import BrickMetadataList
from .fields import BrickRecordFields
from .record_list import BrickRecordList
from .set_status import BrickSetStatus from .set_status import BrickSetStatus
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# Lego sets status list # Lego sets status list
class BrickSetStatusList(BrickRecordList[BrickSetStatus]): class BrickSetStatusList(BrickMetadataList):
statuses: dict[str, BrickSetStatus] kind: str = 'set statuses'
# Database table
table: str = 'bricktracker_set_statuses'
# Queries # Queries
select_query = 'set/metadata/status/list' select_query = 'set/metadata/status/list'
def __init__(self, /, *, force: bool = False): # Filter the list of set status
# Load statuses only if there is none already loaded def filter(self, all: bool = False) -> list[BrickSetStatus]:
records = getattr(self, 'records', None)
if records is None or force:
# Don't use super()__init__ as it would mask class variables
self.fields = BrickRecordFields()
logger.info('Loading set statuses list')
BrickSetStatusList.records = []
BrickSetStatusList.statuses = {}
# Load the statuses from the database
for record in self.select():
status = BrickSetStatus(record=record)
BrickSetStatusList.records.append(status)
BrickSetStatusList.statuses[status.fields.id] = status
# Return the statuses as columns for a select
def as_columns(
self,
/,
*,
solo: bool = False,
table: str = 'bricktracker_set_statuses'
) -> str:
return ', '.join([
'"{table}"."{column}"'.format(
table=table,
column=record.as_column(),
)
for record
in self.records
if solo or record.fields.displayed_on_grid
])
# Grab a specific status
def get(self, id: str, /) -> BrickSetStatus:
if id not in self.statuses:
raise NotFoundException(
'Status with ID {id} was not found in the database'.format(
id=id,
),
)
return self.statuses[id]
# Get the list of statuses depending on the context
def list(self, /, *, all: bool = False) -> list[BrickSetStatus]:
return [ return [
record record
for record for record

View File

@ -41,7 +41,7 @@ def admin() -> str:
database_version = database.version database_version = database.version
database_counters = BrickSQL().count_records() database_counters = BrickSQL().count_records()
metadata_statuses = BrickSetStatusList().list(all=True) metadata_statuses = BrickSetStatusList(BrickSetStatus).list(all=True)
except Exception as e: except Exception as e:
database_exception = e database_exception = e

View File

@ -2,6 +2,7 @@ from flask import Blueprint, render_template
from .exceptions import exception_handler from .exceptions import exception_handler
from ..minifigure_list import BrickMinifigureList from ..minifigure_list import BrickMinifigureList
from ..set_status import BrickSetStatus
from ..set_status_list import BrickSetStatusList from ..set_status_list import BrickSetStatusList
from ..set_list import BrickSetList from ..set_list import BrickSetList
@ -16,5 +17,5 @@ def index() -> str:
'index.html', 'index.html',
brickset_collection=BrickSetList().last(), brickset_collection=BrickSetList().last(),
minifigure_collection=BrickMinifigureList().last(), minifigure_collection=BrickMinifigureList().last(),
brickset_statuses=BrickSetStatusList().list(), brickset_statuses=BrickSetStatusList(BrickSetStatus).list(),
) )

View File

@ -16,6 +16,7 @@ from .exceptions import exception_handler
from ..minifigure import BrickMinifigure from ..minifigure import BrickMinifigure
from ..part import BrickPart from ..part import BrickPart
from ..set import BrickSet from ..set import BrickSet
from ..set_status import BrickSetStatus
from ..set_status_list import BrickSetStatusList from ..set_status_list import BrickSetStatusList
from ..set_list import BrickSetList from ..set_list import BrickSetList
from ..socket import MESSAGES from ..socket import MESSAGES
@ -32,7 +33,7 @@ def list() -> str:
return render_template( return render_template(
'sets.html', 'sets.html',
collection=BrickSetList().all(), collection=BrickSetList().all(),
brickset_statuses=BrickSetStatusList().list(), brickset_statuses=BrickSetStatusList(BrickSetStatus).list(),
) )
@ -42,7 +43,7 @@ def list() -> str:
@exception_handler(__file__, json=True) @exception_handler(__file__, json=True)
def update_status(*, id: str, metadata_id: str) -> Response: def update_status(*, id: str, metadata_id: str) -> Response:
brickset = BrickSet().select_light(id) brickset = BrickSet().select_light(id)
status = BrickSetStatusList().get(metadata_id) status = BrickSetStatusList(BrickSetStatus).get(metadata_id)
state = status.update_set_state(brickset, request.json) state = status.update_set_state(brickset, request.json)
@ -97,7 +98,7 @@ def details(*, id: str) -> str:
'set.html', 'set.html',
item=BrickSet().select_specific(id), item=BrickSet().select_specific(id),
open_instructions=request.args.get('open_instructions'), open_instructions=request.args.get('open_instructions'),
brickset_statuses=BrickSetStatusList().list(all=True), brickset_statuses=BrickSetStatusList(BrickSetStatus).list(all=True),
) )