| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- from abc import ABC, abstractmethod
- from typing import Optional
- from redis._parsers.commands import (
- CommandPolicies,
- CommandsParser,
- PolicyRecords,
- RequestPolicy,
- ResponsePolicy,
- )
- STATIC_POLICIES: PolicyRecords = {
- "ft": {
- "explaincli": CommandPolicies(
- request_policy=RequestPolicy.DEFAULT_KEYLESS,
- response_policy=ResponsePolicy.DEFAULT_KEYLESS,
- ),
- "suglen": CommandPolicies(
- request_policy=RequestPolicy.DEFAULT_KEYED,
- response_policy=ResponsePolicy.DEFAULT_KEYED,
- ),
- "profile": CommandPolicies(
- request_policy=RequestPolicy.DEFAULT_KEYLESS,
- response_policy=ResponsePolicy.DEFAULT_KEYLESS,
- ),
- "dropindex": CommandPolicies(
- request_policy=RequestPolicy.DEFAULT_KEYLESS,
- response_policy=ResponsePolicy.DEFAULT_KEYLESS,
- ),
- "aliasupdate": CommandPolicies(
- request_policy=RequestPolicy.DEFAULT_KEYLESS,
- response_policy=ResponsePolicy.DEFAULT_KEYLESS,
- ),
- "alter": CommandPolicies(
- request_policy=RequestPolicy.DEFAULT_KEYLESS,
- response_policy=ResponsePolicy.DEFAULT_KEYLESS,
- ),
- "aggregate": CommandPolicies(
- request_policy=RequestPolicy.DEFAULT_KEYLESS,
- response_policy=ResponsePolicy.DEFAULT_KEYLESS,
- ),
- "syndump": CommandPolicies(
- request_policy=RequestPolicy.DEFAULT_KEYLESS,
- response_policy=ResponsePolicy.DEFAULT_KEYLESS,
- ),
- "create": CommandPolicies(
- request_policy=RequestPolicy.DEFAULT_KEYLESS,
- response_policy=ResponsePolicy.DEFAULT_KEYLESS,
- ),
- "explain": CommandPolicies(
- request_policy=RequestPolicy.DEFAULT_KEYLESS,
- response_policy=ResponsePolicy.DEFAULT_KEYLESS,
- ),
- "sugget": CommandPolicies(
- request_policy=RequestPolicy.DEFAULT_KEYED,
- response_policy=ResponsePolicy.DEFAULT_KEYED,
- ),
- "dictdel": CommandPolicies(
- request_policy=RequestPolicy.DEFAULT_KEYLESS,
- response_policy=ResponsePolicy.DEFAULT_KEYLESS,
- ),
- "aliasadd": CommandPolicies(
- request_policy=RequestPolicy.DEFAULT_KEYLESS,
- response_policy=ResponsePolicy.DEFAULT_KEYLESS,
- ),
- "dictadd": CommandPolicies(
- request_policy=RequestPolicy.DEFAULT_KEYLESS,
- response_policy=ResponsePolicy.DEFAULT_KEYLESS,
- ),
- "synupdate": CommandPolicies(
- request_policy=RequestPolicy.DEFAULT_KEYLESS,
- response_policy=ResponsePolicy.DEFAULT_KEYLESS,
- ),
- "drop": CommandPolicies(
- request_policy=RequestPolicy.DEFAULT_KEYLESS,
- response_policy=ResponsePolicy.DEFAULT_KEYLESS,
- ),
- "info": CommandPolicies(
- request_policy=RequestPolicy.DEFAULT_KEYLESS,
- response_policy=ResponsePolicy.DEFAULT_KEYLESS,
- ),
- "sugadd": CommandPolicies(
- request_policy=RequestPolicy.DEFAULT_KEYED,
- response_policy=ResponsePolicy.DEFAULT_KEYED,
- ),
- "dictdump": CommandPolicies(
- request_policy=RequestPolicy.DEFAULT_KEYLESS,
- response_policy=ResponsePolicy.DEFAULT_KEYLESS,
- ),
- "cursor": CommandPolicies(
- request_policy=RequestPolicy.SPECIAL,
- response_policy=ResponsePolicy.DEFAULT_KEYLESS,
- ),
- "search": CommandPolicies(
- request_policy=RequestPolicy.DEFAULT_KEYLESS,
- response_policy=ResponsePolicy.DEFAULT_KEYLESS,
- ),
- "tagvals": CommandPolicies(
- request_policy=RequestPolicy.DEFAULT_KEYLESS,
- response_policy=ResponsePolicy.DEFAULT_KEYLESS,
- ),
- "aliasdel": CommandPolicies(
- request_policy=RequestPolicy.DEFAULT_KEYLESS,
- response_policy=ResponsePolicy.DEFAULT_KEYLESS,
- ),
- "sugdel": CommandPolicies(
- request_policy=RequestPolicy.DEFAULT_KEYED,
- response_policy=ResponsePolicy.DEFAULT_KEYED,
- ),
- "spellcheck": CommandPolicies(
- request_policy=RequestPolicy.DEFAULT_KEYLESS,
- response_policy=ResponsePolicy.DEFAULT_KEYLESS,
- ),
- },
- "core": {
- "command": CommandPolicies(
- request_policy=RequestPolicy.DEFAULT_KEYLESS,
- response_policy=ResponsePolicy.DEFAULT_KEYLESS,
- ),
- },
- }
- class PolicyResolver(ABC):
- @abstractmethod
- def resolve(self, command_name: str) -> Optional[CommandPolicies]:
- """
- Resolves the command name and determines the associated command policies.
- Args:
- command_name: The name of the command to resolve.
- Returns:
- CommandPolicies: The policies associated with the specified command.
- """
- pass
- @abstractmethod
- def with_fallback(self, fallback: "PolicyResolver") -> "PolicyResolver":
- """
- Factory method to instantiate a policy resolver with a fallback resolver.
- Args:
- fallback: Fallback resolver
- Returns:
- PolicyResolver: Returns a new policy resolver with the specified fallback resolver.
- """
- pass
- class AsyncPolicyResolver(ABC):
- @abstractmethod
- async def resolve(self, command_name: str) -> Optional[CommandPolicies]:
- """
- Resolves the command name and determines the associated command policies.
- Args:
- command_name: The name of the command to resolve.
- Returns:
- CommandPolicies: The policies associated with the specified command.
- """
- pass
- @abstractmethod
- def with_fallback(self, fallback: "AsyncPolicyResolver") -> "AsyncPolicyResolver":
- """
- Factory method to instantiate an async policy resolver with a fallback resolver.
- Args:
- fallback: Fallback resolver
- Returns:
- AsyncPolicyResolver: Returns a new policy resolver with the specified fallback resolver.
- """
- pass
- class BasePolicyResolver(PolicyResolver):
- """
- Base class for policy resolvers.
- """
- def __init__(
- self, policies: PolicyRecords, fallback: Optional[PolicyResolver] = None
- ) -> None:
- self._policies = policies
- self._fallback = fallback
- def resolve(self, command_name: str) -> Optional[CommandPolicies]:
- parts = command_name.split(".")
- if len(parts) > 2:
- raise ValueError(f"Wrong command or module name: {command_name}")
- module, command = parts if len(parts) == 2 else ("core", parts[0])
- if self._policies.get(module, None) is None:
- if self._fallback is not None:
- return self._fallback.resolve(command_name)
- else:
- return None
- if self._policies.get(module).get(command, None) is None:
- if self._fallback is not None:
- return self._fallback.resolve(command_name)
- else:
- return None
- return self._policies.get(module).get(command)
- @abstractmethod
- def with_fallback(self, fallback: "PolicyResolver") -> "PolicyResolver":
- pass
- class AsyncBasePolicyResolver(AsyncPolicyResolver):
- """
- Async base class for policy resolvers.
- """
- def __init__(
- self, policies: PolicyRecords, fallback: Optional[AsyncPolicyResolver] = None
- ) -> None:
- self._policies = policies
- self._fallback = fallback
- async def resolve(self, command_name: str) -> Optional[CommandPolicies]:
- parts = command_name.split(".")
- if len(parts) > 2:
- raise ValueError(f"Wrong command or module name: {command_name}")
- module, command = parts if len(parts) == 2 else ("core", parts[0])
- if self._policies.get(module, None) is None:
- if self._fallback is not None:
- return await self._fallback.resolve(command_name)
- else:
- return None
- if self._policies.get(module).get(command, None) is None:
- if self._fallback is not None:
- return await self._fallback.resolve(command_name)
- else:
- return None
- return self._policies.get(module).get(command)
- @abstractmethod
- def with_fallback(self, fallback: "AsyncPolicyResolver") -> "AsyncPolicyResolver":
- pass
- class DynamicPolicyResolver(BasePolicyResolver):
- """
- Resolves policy dynamically based on the COMMAND output.
- """
- def __init__(
- self, commands_parser: CommandsParser, fallback: Optional[PolicyResolver] = None
- ) -> None:
- """
- Parameters:
- commands_parser (CommandsParser): COMMAND output parser.
- fallback (Optional[PolicyResolver]): An optional resolver to be used when the
- primary policies cannot handle a specific request.
- """
- self._commands_parser = commands_parser
- super().__init__(commands_parser.get_command_policies(), fallback)
- def with_fallback(self, fallback: "PolicyResolver") -> "PolicyResolver":
- return DynamicPolicyResolver(self._commands_parser, fallback)
- class StaticPolicyResolver(BasePolicyResolver):
- """
- Resolves policy from a static list of policy records.
- """
- def __init__(self, fallback: Optional[PolicyResolver] = None) -> None:
- """
- Parameters:
- fallback (Optional[PolicyResolver]): An optional fallback policy resolver
- used for resolving policies if static policies are inadequate.
- """
- super().__init__(STATIC_POLICIES, fallback)
- def with_fallback(self, fallback: "PolicyResolver") -> "PolicyResolver":
- return StaticPolicyResolver(fallback)
- class AsyncDynamicPolicyResolver(AsyncBasePolicyResolver):
- """
- Async version of DynamicPolicyResolver.
- """
- def __init__(
- self,
- policy_records: PolicyRecords,
- fallback: Optional[AsyncPolicyResolver] = None,
- ) -> None:
- """
- Parameters:
- policy_records (PolicyRecords): Policy records.
- fallback (Optional[AsyncPolicyResolver]): An optional resolver to be used when the
- primary policies cannot handle a specific request.
- """
- super().__init__(policy_records, fallback)
- def with_fallback(self, fallback: "AsyncPolicyResolver") -> "AsyncPolicyResolver":
- return AsyncDynamicPolicyResolver(self._policies, fallback)
- class AsyncStaticPolicyResolver(AsyncBasePolicyResolver):
- """
- Async version of StaticPolicyResolver.
- """
- def __init__(self, fallback: Optional[AsyncPolicyResolver] = None) -> None:
- """
- Parameters:
- fallback (Optional[AsyncPolicyResolver]): An optional fallback policy resolver
- used for resolving policies if static policies are inadequate.
- """
- super().__init__(STATIC_POLICIES, fallback)
- def with_fallback(self, fallback: "AsyncPolicyResolver") -> "AsyncPolicyResolver":
- return AsyncStaticPolicyResolver(fallback)
|