Files
bricktracker
migrations
sql
views
__init__.py
app.py
config.py
configuration.py
configuration_list.py
exceptions.py
fields.py
instructions.py
instructions_list.py
login.py
minifigure.py
minifigure_list.py
navbar.py
parser.py
part.py
part_list.py
rebrickable.py
rebrickable_image.py
rebrickable_minifigure.py
rebrickable_part.py
rebrickable_set.py
rebrickable_set_list.py
record.py
record_list.py
reload.py
retired.py
retired_list.py
set.py
set_checkbox.py
set_checkbox_list.py
set_list.py
socket.py
socket_decorator.py
sql.py
sql_counter.py
sql_migration.py
sql_migration_list.py
sql_stats.py
theme.py
theme_list.py
version.py
wish.py
wish_list.py
docs
static
templates
.dockerignore
.env.sample
.gitignore
CHANGELOG.md
Dockerfile
LICENSE
README.md
__init__.py
app.py
compose.legacy.yml
compose.local.yaml
compose.yaml
entrypoint.sh
requirements.txt
test-server.sh
BrickTracker/bricktracker/instructions_list.py

107 lines
3.9 KiB
Python

import logging
import os
from typing import Generator, TYPE_CHECKING
from flask import current_app
from .exceptions import NotFoundException
from .instructions import BrickInstructions
from .rebrickable_set_list import RebrickableSetList
if TYPE_CHECKING:
from .rebrickable_set import RebrickableSet
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'],
)
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.set:
# Instantiate the list if not existing yet
if instruction.set not in BrickInstructionsList.sets: # noqa: E501
BrickInstructionsList.sets[instruction.set] = [] # noqa: E501
BrickInstructionsList.sets[instruction.set].append(instruction) # noqa: E501
BrickInstructionsList.sets_total += 1
else:
BrickInstructionsList.unknown_total += 1
else:
BrickInstructionsList.rejected_total += 1
# List of Rebrickable sets
rebrickable_sets: dict[str, RebrickableSet] = {}
for rebrickable_set in RebrickableSetList().all():
rebrickable_sets[rebrickable_set.fields.set] = rebrickable_set # noqa: E501
# Inject the brickset if it exists
for instruction in self.all.values():
if (
instruction.allowed and
instruction.set is not None and
instruction.rebrickable is None and
instruction.set in rebrickable_sets
):
instruction.rebrickable = rebrickable_sets[instruction.set] # noqa: E501
# Ignore errors
except Exception:
pass
# Grab instructions for a set
def get(self, set: str) -> list[BrickInstructions]:
if set in self.sets:
return self.sets[set]
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]