BrickTracker/bricktracker/set.py

189 lines
5.4 KiB
Python
Raw Normal View History

import logging
import traceback
2025-01-17 11:03:00 +01:00
from typing import Any, Self
from uuid import uuid4
2025-01-17 11:03:00 +01:00
from flask import current_app, url_for
2025-01-17 11:03:00 +01:00
from .exceptions import DatabaseException, NotFoundException
from .minifigure_list import BrickMinifigureList
from .part_list import BrickPartList
from .rebrickable_minifigures import RebrickableMinifigures
from .rebrickable_parts import RebrickableParts
from .rebrickable_set import RebrickableSet
from .set_checkbox import BrickSetCheckbox
from .set_checkbox_list import BrickSetCheckboxList
2025-01-17 11:03:00 +01:00
from .sql import BrickSQL
logger = logging.getLogger(__name__)
2025-01-17 11:03:00 +01:00
# Lego brick set
class BrickSet(RebrickableSet):
2025-01-17 11:03:00 +01:00
# Queries
select_query: str = 'set/select/full'
light_query: str = 'set/select/light'
2025-01-17 11:03:00 +01:00
insert_query: str = 'set/insert'
# Delete a set
def delete(self, /) -> None:
BrickSQL().executescript(
'set/delete/set',
id=self.fields.id
)
2025-01-17 11:03:00 +01:00
# Import a set into the database
def download(self, data: dict[str, Any], /) -> None:
# Load the set
if not self.load(data, from_download=True):
return
2025-01-17 11:03:00 +01:00
try:
# Insert into the database
self.socket.auto_progress(
message='Set {number}: inserting into database'.format(
number=self.fields.set
),
increment_total=True,
)
2025-01-17 11:03:00 +01:00
# Generate an UUID for self
self.fields.id = str(uuid4())
2025-01-17 11:03:00 +01:00
# Insert into database
self.insert(commit=False)
2025-01-17 11:03:00 +01:00
# Execute the parent download method
self.insert_rebrickable()
# Load the inventory
RebrickableParts(self.socket, self).download()
# Load the minifigures
RebrickableMinifigures(self.socket, self).download()
# Commit the transaction to the database
self.socket.auto_progress(
message='Set {number}: writing to the database'.format(
number=self.fields.set
),
increment_total=True,
)
2025-01-17 11:03:00 +01:00
BrickSQL().commit()
2025-01-17 11:03:00 +01:00
# Info
logger.info('Set {number}: imported (id: {id})'.format(
number=self.fields.set,
id=self.fields.id,
))
# Complete
self.socket.complete(
message='Set {number}: imported (<a href="{url}">Go to the set</a>)'.format( # noqa: E501
number=self.fields.set,
url=self.url()
),
download=True
)
2025-01-17 11:03:00 +01:00
except Exception as e:
self.socket.fail(
message='Error while importing set {number}: {error}'.format(
number=self.fields.set,
error=e,
)
)
2025-01-17 11:03:00 +01:00
logger.debug(traceback.format_exc())
2025-01-17 11:03:00 +01:00
# Minifigures
def minifigures(self, /) -> BrickMinifigureList:
return BrickMinifigureList().load(self)
# Parts
def parts(self, /) -> BrickPartList:
return BrickPartList().load(self)
# Select a light set (with an id)
def select_light(self, id: str, /) -> Self:
2025-01-17 11:03:00 +01:00
# Save the parameters to the fields
self.fields.id = id
2025-01-17 11:03:00 +01:00
# Load from database
if not self.select(override_query=self.light_query):
2025-01-17 11:03:00 +01:00
raise NotFoundException(
'Set with ID {id} was not found in the database'.format(
id=self.fields.id,
2025-01-17 11:03:00 +01:00
),
)
return self
2025-01-17 11:03:00 +01:00
# Select a specific set (with an id)
def select_specific(self, id: str, /) -> Self:
# Save the parameters to the fields
self.fields.id = id
# Load from database
if not self.select(
statuses=BrickSetCheckboxList().as_columns(solo=True)
):
raise NotFoundException(
'Set with ID {id} was not found in the database'.format(
id=self.fields.id,
),
)
2025-01-17 11:03:00 +01:00
return self
# Update a status
def update_status(
self,
checkbox: BrickSetCheckbox,
status: bool,
/
) -> None:
2025-01-17 11:03:00 +01:00
parameters = self.sql_parameters()
parameters['status'] = status
# Update the status
2025-01-17 11:03:00 +01:00
rows, _ = BrickSQL().execute_and_commit(
'set/update/status',
2025-01-17 11:03:00 +01:00
parameters=parameters,
name=checkbox.as_column(),
2025-01-17 11:03:00 +01:00
)
if rows != 1:
raise DatabaseException('Could not update the status "{status}" for set {number} ({id})'.format( # noqa: E501
status=checkbox.fields.name,
number=self.fields.set,
id=self.fields.id,
2025-01-17 11:03:00 +01:00
))
# Self url
def url(self, /) -> str:
return url_for('set.details', id=self.fields.id)
2025-01-17 11:03:00 +01:00
# Deletion url
def url_for_delete(self, /) -> str:
return url_for('set.delete', id=self.fields.id)
2025-01-17 11:03:00 +01:00
# Actual deletion url
def url_for_do_delete(self, /) -> str:
return url_for('set.do_delete', id=self.fields.id)
2025-01-17 11:03:00 +01:00
# Compute the url for the set instructions
def url_for_instructions(self, /) -> str:
if (
not current_app.config['HIDE_SET_INSTRUCTIONS'] and
len(self.instructions)
):
2025-01-17 11:03:00 +01:00
return url_for(
'set.details',
id=self.fields.id,
2025-01-17 11:03:00 +01:00
open_instructions=True
)
else:
return ''