111 lines
3.9 KiB
Python
111 lines
3.9 KiB
Python
import logging
|
|
import os
|
|
from typing import Generator
|
|
|
|
from flask import current_app
|
|
|
|
from .exceptions import NotFoundException
|
|
from .instructions import BrickInstructions
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
# Lego sets instruction list
|
|
class BrickInstructionsList(object):
|
|
all: dict[str, BrickInstructions]
|
|
rejected_total: int
|
|
sets: dict[str, list[BrickInstructions]]
|
|
sets_total: int
|
|
unknown_total: int
|
|
|
|
def __init__(self, /, force=False):
|
|
# Load instructions only if there is none already loaded
|
|
all = getattr(self, 'all', None)
|
|
|
|
if all is None or force:
|
|
logger.info('Loading instructions file list')
|
|
|
|
BrickInstructionsList.all = {}
|
|
BrickInstructionsList.rejected_total = 0
|
|
BrickInstructionsList.sets = {}
|
|
BrickInstructionsList.sets_total = 0
|
|
BrickInstructionsList.unknown_total = 0
|
|
|
|
# Try to list the files in the instruction folder
|
|
try:
|
|
# Make a folder relative to static
|
|
folder: str = os.path.join(
|
|
current_app.static_folder, # type: ignore
|
|
current_app.config['INSTRUCTIONS_FOLDER'].value,
|
|
)
|
|
|
|
for file in os.scandir(folder):
|
|
instruction = BrickInstructions(file)
|
|
|
|
# Unconditionnally add to the list
|
|
BrickInstructionsList.all[instruction.filename] = instruction # noqa: E501
|
|
|
|
if instruction.allowed:
|
|
if instruction.number:
|
|
# Instantiate the list if not existing yet
|
|
if instruction.number not in BrickInstructionsList.sets: # noqa: E501
|
|
BrickInstructionsList.sets[instruction.number] = [] # noqa: E501
|
|
|
|
BrickInstructionsList.sets[instruction.number].append(instruction) # noqa: E501
|
|
BrickInstructionsList.sets_total += 1
|
|
else:
|
|
BrickInstructionsList.unknown_total += 1
|
|
else:
|
|
BrickInstructionsList.rejected_total += 1
|
|
|
|
# Associate bricksets
|
|
# Not ideal, to avoid a circular import
|
|
from .set import BrickSet
|
|
from .set_list import BrickSetList
|
|
|
|
# Grab the generic list of sets
|
|
bricksets: dict[str, BrickSet] = {}
|
|
for brickset in BrickSetList().generic().records:
|
|
bricksets[brickset.fields.set_num] = brickset
|
|
|
|
# Return the files
|
|
for instruction in self.all.values():
|
|
# Inject the brickset if it exists
|
|
if (
|
|
instruction.allowed and
|
|
instruction.number is not None and
|
|
instruction.brickset is None and
|
|
instruction.number in bricksets
|
|
):
|
|
instruction.brickset = bricksets[instruction.number]
|
|
|
|
# Ignore errors
|
|
except Exception:
|
|
pass
|
|
|
|
# Grab instructions for a set
|
|
def get(self, number: str) -> list[BrickInstructions]:
|
|
if number in self.sets:
|
|
return self.sets[number]
|
|
else:
|
|
return []
|
|
|
|
# Grab instructions for a file
|
|
def get_file(self, name: str) -> BrickInstructions:
|
|
if name not in self.all:
|
|
raise NotFoundException('Instruction file {name} does not exist'.format( # noqa: E501
|
|
name=name
|
|
))
|
|
|
|
return self.all[name]
|
|
|
|
# List of all instruction files
|
|
def list(self, /) -> Generator[BrickInstructions, None, None]:
|
|
# Get the filenames and sort them
|
|
filenames = list(self.all.keys())
|
|
filenames.sort()
|
|
|
|
# Return the files
|
|
for filename in filenames:
|
|
yield self.all[filename]
|