From cbf54d442c37fb774b7e6708b9c2f3404df8bcaa Mon Sep 17 00:00:00 2001 From: Marek Wolan Date: Mon, 8 Jul 2024 15:17:35 +0100 Subject: [PATCH] #2623 Make it possible to view currently valid simulation requests --- src/primaite/simulator/core.py | 31 ++++++++++++++++----- src/primaite/simulator/domain/controller.py | 2 ++ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/primaite/simulator/core.py b/src/primaite/simulator/core.py index 8d8425ec..be5eb4b9 100644 --- a/src/primaite/simulator/core.py +++ b/src/primaite/simulator/core.py @@ -3,9 +3,10 @@ """Core of the PrimAITE Simulator.""" import warnings from abc import abstractmethod -from typing import Callable, Dict, List, Literal, Optional, Union +from typing import Callable, Dict, List, Literal, Optional, Tuple, Union from uuid import uuid4 +from prettytable import PrettyTable from pydantic import BaseModel, ConfigDict, Field, validate_call from primaite import getLogger @@ -150,18 +151,34 @@ class RequestManager(BaseModel): self.request_types.pop(name) - def get_request_types_recursively(self) -> List[List[str]]: - """Recursively generate request tree for this component.""" + def get_request_types_recursively(self, _parent_valid: bool = True) -> List[Tuple[RequestFormat, bool]]: + """ + Recursively generate request tree for this component. + + :param parent_valid: Whether this sub-request's parent request was valid. This value should not be specified by + users, it is used by the recursive call. + :type parent_valid: bool + :returns: A list of tuples where the first tuple element is the request string and the second is whether that + request is currently possible to execute. + :rtype: List[Tuple[RequestFormat, bool]] + """ requests = [] for req_name, req in self.request_types.items(): + valid = req.validator([], {}) and _parent_valid # if parent is invalid, all children are invalid if isinstance(req.func, RequestManager): - sub_requests = req.func.get_request_types_recursively() - sub_requests = [[req_name] + a for a in sub_requests] + sub_requests = req.func.get_request_types_recursively(valid) # recurse + sub_requests = [([req_name] + a, valid) for a, valid in sub_requests] # prepend parent request to leaf requests.extend(sub_requests) - else: - requests.append([req_name]) + else: # leaf node found + requests.append(([req_name], valid)) return requests + def show(self) -> None: + table = PrettyTable(["request", "valid"]) + table.align = "l" + table.add_rows(self.get_request_types_recursively()) + print(table) + class SimComponent(BaseModel): """Extension of pydantic BaseModel with additional methods that must be defined by all classes in the simulator.""" diff --git a/src/primaite/simulator/domain/controller.py b/src/primaite/simulator/domain/controller.py index 37e60aaa..a264ba24 100644 --- a/src/primaite/simulator/domain/controller.py +++ b/src/primaite/simulator/domain/controller.py @@ -52,6 +52,8 @@ class GroupMembershipValidator(RequestPermissionValidator): def __call__(self, request: List[str], context: Dict) -> bool: """Permit the action if the request comes from an account which belongs to the right group.""" # if context request source is part of any groups mentioned in self.allow_groups, return true, otherwise false + if not context: + return False requestor_groups: List[str] = context["request_source"]["groups"] for allowed_group in self.allowed_groups: if allowed_group.name in requestor_groups: