Skip to content

Instantly share code, notes, and snippets.

@joffilyfe
Created December 10, 2023 16:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joffilyfe/afd200856fd80c29e64367a8ea99332a to your computer and use it in GitHub Desktop.
Save joffilyfe/afd200856fd80c29e64367a8ea99332a to your computer and use it in GitHub Desktop.
Implements the EntryPoint command pattern in Python
from typing import Any, List, Optional, TypeVar, Generic, Protocol, ClassVar, Sequence, Union, Iterable
from polls.models import Question
class BaseAuthorizer:
"""BaseAuthorizer defines how child classes should behavior
when called by EntryPoints"""
def __init__(self, entry_point: "BaseEntryPoint") -> None:
self.entry_point = entry_point
def check(self) -> None:
raise NotImplementedError
class ActionBase:
"""ActionBase class defines how action classes behave"""
def __call__(self):
raise NotImplementedError
class AuthorizerError(Exception):
...
TAuthorizer = TypeVar("TAuthorizer", bound=BaseAuthorizer)
# TAuthorizer = TypeVar("TAuthorizer", covariant=True)
class UserAuthorizer(BaseAuthorizer):
def check(self):
"""Check if the user/employee/person has permission to perform
this action"""
if self.entry_point.user["name"] == "Joffily":
return None
raise AuthorizerError("User not authorized")
class PollAction(ActionBase):
def __init__(self, user: dict) -> None:
self.user = user
def __call__(self):
print(f"PollAction.call, user: {self.user}")
class BaseEntryPoint:
"""Base class that defines how authorizers and actions are called.
Every unit that use entry point pattern should inherent from here."""
authorizers: Iterable[BaseAuthorizer] = []
action: Optional[ActionBase] = None
def execute(self):
self.run_authorizers()
if hasattr(self, "action"):
self.action()
if hasattr(self, "form"):
...
def run_authorizers(self):
for authorizer in self.authorizers:
print(f"Executing authorizer <{authorizer.__name__}>")
authorizer(self).check()
def entry_point(cls):
"""Decorates entry points classes"""
class Base(cls, BaseEntryPoint):
...
return Base
class EntryPoint(BaseEntryPoint):
authorizers = [UserAuthorizer]
def __init__(self, name):
self.name = name
self.action = PollAction(user=self.user)
@property
def user(self):
return {"name": self.name}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment