Source code for simstack.core.resources
import logging
from typing import List
logger = logging.getLogger("resources")
[docs]
class AllowedResources:
"""
Singleton class that holds a list of allowed resource strings.
This class is problematic because the @node decorator is called before the config is read.
@node may contain Parameters which set default values for resources.
The solution is to create the AllowedResources singleton class here, and set the resources from
context.initialize. Before context.initialize is called, any resource is allowed.
However, resources are validated on read, so before any node is executed, the resources must be set.
AllowedResources can be set only once.
"""
_instance = None
_resources: List[str] = []
def __new__(cls):
if cls._instance is None:
cls._instance = super(AllowedResources, cls).__new__(cls)
return cls._instance
def __init__(self):
# Only initialize once
self._initialized = False
[docs]
def set_resources(self, resources: List[str]) -> None:
"""Set the list of allowed resources."""
if self._initialized and resources != self._resources:
raise RuntimeError("Resources can only be set once")
self._initialized = True
self._resources = resources.copy() if resources else []
[docs]
def get_resources(self) -> List[str]:
"""Get the list of allowed resources."""
return self._resources.copy()
[docs]
def add_resource(self, resource: str) -> None:
"""Add a single resource to the list."""
if resource not in self._resources:
self._resources.append(resource)
[docs]
def remove_resource(self, resource: str) -> None:
if resource == "self":
raise ValueError("Cannot remove 'self' resource")
"""Remove a resource from the list."""
if resource in self._resources:
self._resources.remove(resource)
[docs]
def clear_resources(self) -> None:
"""Clear all resources from the list."""
self._resources.clear()
self._initialized = False
[docs]
def has_resource(self, resource: str) -> bool:
"""Check if a resource exists in the list."""
if hasattr(self, "_initialized") and self._initialized:
return resource in self._resources
else:
return True # before this is initialized, any resource is allowed
def __len__(self) -> int:
"""Return the number of resources."""
return len(self._resources)
def __iter__(self):
"""Make the class iterable."""
return iter(self._resources)
def __contains__(self, resource: str) -> bool:
"""Support 'in' operator."""
return resource in self._resources
def __str__(self) -> str:
"""String representation."""
return f"AllowedResources({self._resources})"
def __repr__(self) -> str:
"""String representation."""
return f"AllowedResources({self._resources!r})"
@property
def initialized(self):
return hasattr(self, "_initialized")
allowed_resources = AllowedResources()