import inspect
from typing import Any
from apparser.core import BaseUi
from apparser.instructions import BaseInstruction
from apparser.instructions.debuggers import BaseDebugger, Debugger
from apparser.instructions.ui.algorithms.base import BaseAlgorithm
from apparser.instructions.utils import get_instruction_by_id
def _check_instruction(instruction: tuple[int, list[Any]]) -> tuple[int, list[Any]]:
if not isinstance(instruction, tuple):
raise TypeError(f"{instruction} must be tuple")
instruction_id, instruction_args = instruction
if not isinstance(instruction_id, int):
raise TypeError(f"{instruction_id} must be int")
if not isinstance(instruction_args, list):
raise TypeError(f"{instruction_args} must be list")
return instruction_id, instruction_args
[docs]
class IdsAlgorithm(BaseAlgorithm):
"""Resolve and execute instructions by their numeric identifiers."""
def __init__(self,
instructions: list[tuple[int, list[Any]]],
attributes: list[Any],
debugger: BaseDebugger | bool = True):
"""Initialize an identifier-based instruction algorithm.
:param instructions: Sequence of instruction identifiers with their arguments.
:type instructions: list[tuple[int, list[Any]]]
:param attributes: Attribute values matched to instruction parameters by type.
:type attributes: list[Any]
:param debugger: Debugger used to wrap instruction execution. If True, use Debugger. If False do not wrap instruction execution.
:type debugger: BaseDebugger | bool
:raises TypeError: If ``debugger`` has an invalid type.
"""
if not isinstance(debugger, BaseDebugger) and not isinstance(debugger, bool):
raise TypeError(f"debugger must be a bool or BaseDebugger")
if debugger == True:
debugger = Debugger()
elif debugger == False:
debugger = None
attributes.reverse()
self.__debugger = debugger
self.__instructions = instructions
self.__attributes = attributes
@property
def id(self) -> int:
return 1501
def __form_args(self, instruction: BaseInstruction) -> dict[str, Any]:
result = {}
function_signature = inspect.signature(instruction.perform)
for arg in function_signature.parameters.values():
for a in self.__attributes:
if arg.annotation is type(a):
result[arg.name] = a
return result
[docs]
def add_instruction(self, instruction: tuple[int, list[Any]]):
_check_instruction(instruction)
self.__instructions.append(instruction)
@property
def instructions(self) -> list[tuple[int, list[Any]]]:
return self.__instructions