Skip to content

Commit 7d1dfd8

Browse files
author
Mathias BIGAIGNON
committed
Re-add policy auto-discovery
1 parent 29675b8 commit 7d1dfd8

File tree

1 file changed

+36
-9
lines changed

1 file changed

+36
-9
lines changed

entitled/client.py

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,53 @@
1-
import re
1+
from importlib import util
2+
from pathlib import Path
3+
import types
24
from typing import Any, Literal
35

46
from entitled.exceptions import AuthorizationException
57
from entitled.policies import Policy
68
from entitled.response import Err, Response
7-
from entitled.rules import Actor, Rule, RuleProto
89

910

1011
class Client:
11-
def __init__(self):
12-
self._policy_registry: dict[type, Policy[Any]] = {}
13-
self._rule_registry: dict[str, Rule[Any]] = {}
12+
load_path: Path | None = None
13+
_policy_registry: dict[type, Policy[Any]]
1414

15-
def define_rule(self, name: str, callable: RuleProto[Actor]) -> Rule[Actor]:
16-
rule = Rule(name, callable)
17-
self._rule_registry[rule.name] = rule
18-
return rule
15+
def __init__(self, path: str | None = None):
16+
self._policy_registry = dict()
17+
if path is not None:
18+
self.load_path = Path(path)
19+
self.load_policies()
1920

2021
def register_policy(self, policy: Policy[Any]):
2122
resource_type = getattr(policy, "__orig_class__").__args__[0]
2223
self._policy_registry[resource_type] = policy
2324

25+
def load_policies(self, path: Path | None = None):
26+
path = path if path is not None else self.load_path
27+
if path is None:
28+
return
29+
for file in path.glob("*.py"):
30+
mod_name = file.stem
31+
full_mod_name = ".".join(file.parts[:-1] + (mod_name,))
32+
spec = util.spec_from_file_location(full_mod_name, file)
33+
if spec is not None:
34+
mod = util.module_from_spec(spec)
35+
if spec.loader:
36+
try:
37+
spec.loader.exec_module(mod)
38+
self._register_from_module(mod)
39+
except Exception as e:
40+
raise e
41+
42+
def _register_from_module(self, mod: types.ModuleType):
43+
for attr_name in dir(mod):
44+
attr = getattr(mod, attr_name)
45+
if isinstance(attr, Policy):
46+
try:
47+
self.register_policy(attr)
48+
except (ValueError, AttributeError):
49+
pass
50+
2451
def _resolve_policy(self, resource: Any) -> Policy[Any] | None:
2552
lookup_key = resource if isinstance(resource, type) else type(resource)
2653
policy = self._policy_registry.get(lookup_key, None)

0 commit comments

Comments
 (0)