BrickTracker/bricktracker/minifigure_list.py

184 lines
5.1 KiB
Python
Raw Normal View History

2025-01-27 18:39:35 +01:00
import logging
import traceback
2025-01-17 11:03:00 +01:00
from typing import Any, Self, TYPE_CHECKING
from flask import current_app
from .minifigure import BrickMinifigure
2025-01-27 18:39:35 +01:00
from .rebrickable import Rebrickable
2025-01-17 11:03:00 +01:00
from .record_list import BrickRecordList
if TYPE_CHECKING:
from .set import BrickSet
2025-01-27 18:39:35 +01:00
from .socket import BrickSocket
logger = logging.getLogger(__name__)
2025-01-17 11:03:00 +01:00
# Lego minifigures
class BrickMinifigureList(BrickRecordList[BrickMinifigure]):
brickset: 'BrickSet | None'
order: str
2025-01-17 11:03:00 +01:00
# Queries
all_query: str = 'minifigure/list/all'
2025-01-31 20:46:36 +01:00
damaged_part_query: str = 'minifigure/list/damaged_part'
2025-01-17 11:03:00 +01:00
last_query: str = 'minifigure/list/last'
2025-01-31 20:46:36 +01:00
missing_part_query: str = 'minifigure/list/missing_part'
2025-01-17 11:03:00 +01:00
select_query: str = 'minifigure/list/from_set'
using_part_query: str = 'minifigure/list/using_part'
def __init__(self, /):
super().__init__()
# Placeholders
self.brickset = None
# Store the order for this list
self.order = current_app.config['MINIFIGURES_DEFAULT_ORDER']
2025-01-17 11:03:00 +01:00
# Load all minifigures
def all(self, /) -> Self:
self.list(override_query=self.all_query)
2025-01-17 11:03:00 +01:00
return self
2025-01-31 20:46:36 +01:00
# Minifigures with a part damaged part
def damaged_part(self, part: str, color: int, /) -> Self:
# Save the parameters to the fields
self.fields.part = part
self.fields.color = color
# Load the minifigures from the database
self.list(override_query=self.damaged_part_query)
2025-01-31 20:46:36 +01:00
return self
2025-01-17 11:03:00 +01:00
# Last added minifigure
def last(self, /, *, limit: int = 6) -> Self:
2025-01-17 11:03:00 +01:00
# Randomize
if current_app.config['RANDOM']:
2025-01-17 11:03:00 +01:00
order = 'RANDOM()'
else:
2025-01-27 18:39:35 +01:00
order = '"bricktracker_minifigures"."rowid" DESC'
2025-01-17 11:03:00 +01:00
self.list(override_query=self.last_query, order=order, limit=limit)
return self
# Base minifigure list
def list(
self,
/,
*,
override_query: str | None = None,
order: str | None = None,
limit: int | None = None,
**context: Any,
) -> None:
if order is None:
order = self.order
if hasattr(self, 'brickset'):
brickset = self.brickset
else:
brickset = None
# Load the sets from the database
for record in super().select(
override_query=override_query,
2025-01-17 11:03:00 +01:00
order=order,
limit=limit,
2025-01-17 11:03:00 +01:00
):
minifigure = BrickMinifigure(brickset=brickset, record=record)
2025-01-17 11:03:00 +01:00
self.records.append(minifigure)
# Load minifigures from a brickset
2025-01-27 17:07:30 +01:00
def from_set(self, brickset: 'BrickSet', /) -> Self:
2025-01-17 11:03:00 +01:00
# Save the brickset
self.brickset = brickset
# Load the minifigures from the database
self.list()
2025-01-17 11:03:00 +01:00
return self
# Minifigures missing a part
2025-01-31 20:46:36 +01:00
def missing_part(self, part: str, color: int, /) -> Self:
2025-01-17 11:03:00 +01:00
# Save the parameters to the fields
2025-01-28 19:18:51 +01:00
self.fields.part = part
self.fields.color = color
2025-01-17 11:03:00 +01:00
# Load the minifigures from the database
self.list(override_query=self.missing_part_query)
2025-01-17 11:03:00 +01:00
return self
# Minifigure using a part
2025-01-31 20:46:36 +01:00
def using_part(self, part: str, color: int, /) -> Self:
2025-01-17 11:03:00 +01:00
# Save the parameters to the fields
2025-01-28 19:18:51 +01:00
self.fields.part = part
self.fields.color = color
2025-01-17 11:03:00 +01:00
# Load the minifigures from the database
self.list(override_query=self.using_part_query)
2025-01-17 11:03:00 +01:00
return self
2025-01-27 18:39:35 +01:00
# Return a dict with common SQL parameters for a minifigures list
def sql_parameters(self, /) -> dict[str, Any]:
parameters: dict[str, Any] = super().sql_parameters()
if self.brickset is not None:
2025-01-27 23:07:10 +01:00
parameters['id'] = self.brickset.fields.id
2025-01-27 18:39:35 +01:00
return parameters
# Import the minifigures from Rebrickable
@staticmethod
2025-01-28 23:07:12 +01:00
def download(
socket: 'BrickSocket',
brickset: 'BrickSet',
/,
*,
refresh: bool = False
) -> bool:
2025-01-27 18:39:35 +01:00
try:
socket.auto_progress(
message='Set {set}: loading minifigures from Rebrickable'.format( # noqa: E501
set=brickset.fields.set,
),
increment_total=True,
)
logger.debug('rebrick.lego.get_set_minifigs("{set}")'.format(
set=brickset.fields.set,
))
minifigures = Rebrickable[BrickMinifigure](
'get_set_minifigs',
brickset.fields.set,
BrickMinifigure,
socket=socket,
brickset=brickset,
).list()
# Process each minifigure
for minifigure in minifigures:
2025-01-28 23:07:12 +01:00
if not minifigure.download(socket, refresh=refresh):
2025-01-28 19:18:51 +01:00
return False
return True
2025-01-27 18:39:35 +01:00
except Exception as e:
socket.fail(
message='Error while importing set {set} minifigure list: {error}'.format( # noqa: E501
set=brickset.fields.set,
error=e,
)
)
logger.debug(traceback.format_exc())
2025-01-28 19:18:51 +01:00
return False