python-library-registry 0.1.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
registry/__init__.py,sha256=nr8Rs-Uw75XbgEja-cbbCVwLXw7rZOqLwzc4Goe16ZQ,3685
|
|
2
|
+
python_library_registry-0.1.3.dist-info/METADATA,sha256=H4UHpvTIerp4x9BZCNwhmqvPE4OFkuDtjuyjfbIQmyo,132
|
|
3
|
+
python_library_registry-0.1.3.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
4
|
+
python_library_registry-0.1.3.dist-info/RECORD,,
|
registry/__init__.py
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from difflib import get_close_matches
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from pydantic import Field
|
|
7
|
+
from tree_model import TreeModel
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class EntryNode(TreeModel):
|
|
11
|
+
obj: Any | None = Field(default=None, description="注册对象")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Registry:
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
namespace: str = "",
|
|
18
|
+
*,
|
|
19
|
+
_root: EntryNode | None = None,
|
|
20
|
+
) -> None:
|
|
21
|
+
"""
|
|
22
|
+
Args:
|
|
23
|
+
namespace: 命名空间
|
|
24
|
+
Attributes:
|
|
25
|
+
_namespace: 命名空间
|
|
26
|
+
_root: 根节点
|
|
27
|
+
"""
|
|
28
|
+
self._namespace = namespace.strip(".")
|
|
29
|
+
self._root = EntryNode(name="") if _root is None else _root
|
|
30
|
+
|
|
31
|
+
def _full_name(self, name: str) -> str:
|
|
32
|
+
if not self._namespace:
|
|
33
|
+
return name
|
|
34
|
+
return f"{self._namespace}.{name}"
|
|
35
|
+
|
|
36
|
+
def _get_or_create_node(self, full_name: str) -> EntryNode:
|
|
37
|
+
node = self._root
|
|
38
|
+
for part in filter(None, full_name.split(".")):
|
|
39
|
+
child = node.find_child(lambda item: item.name == part)
|
|
40
|
+
if child is None:
|
|
41
|
+
child = EntryNode(name=part)
|
|
42
|
+
node.add_child(child)
|
|
43
|
+
node = child
|
|
44
|
+
return node
|
|
45
|
+
|
|
46
|
+
def _find_node(self, full_name: str) -> EntryNode | None:
|
|
47
|
+
node: EntryNode = self._root
|
|
48
|
+
for part in filter(None, full_name.split(".")):
|
|
49
|
+
found = node.find_child(lambda item: item.name == part)
|
|
50
|
+
if found is None:
|
|
51
|
+
return None
|
|
52
|
+
node = found
|
|
53
|
+
return node
|
|
54
|
+
|
|
55
|
+
def get_registered_names(self) -> list[str]:
|
|
56
|
+
"""获取已注册的名称列表"""
|
|
57
|
+
names: list[str] = []
|
|
58
|
+
|
|
59
|
+
def walk(node: EntryNode) -> None:
|
|
60
|
+
if node.obj is not None and node.full_name:
|
|
61
|
+
names.append(node.full_name)
|
|
62
|
+
for child in node:
|
|
63
|
+
walk(child)
|
|
64
|
+
|
|
65
|
+
for child in self._root:
|
|
66
|
+
walk(child)
|
|
67
|
+
|
|
68
|
+
return names
|
|
69
|
+
|
|
70
|
+
def _suggest_name(self, full_name: str) -> str | None:
|
|
71
|
+
matches = get_close_matches(
|
|
72
|
+
full_name,
|
|
73
|
+
self.get_registered_names(),
|
|
74
|
+
n=1,
|
|
75
|
+
cutoff=0.6,
|
|
76
|
+
)
|
|
77
|
+
return matches[0] if matches else None
|
|
78
|
+
|
|
79
|
+
def register(self, name: str, obj: Any) -> Any:
|
|
80
|
+
"""注册对象"""
|
|
81
|
+
full_name = self._full_name(name)
|
|
82
|
+
|
|
83
|
+
node = self._get_or_create_node(full_name)
|
|
84
|
+
if node.obj is not None:
|
|
85
|
+
raise ValueError(f"重复注册 {full_name!r}")
|
|
86
|
+
node.obj = obj
|
|
87
|
+
return obj
|
|
88
|
+
|
|
89
|
+
def __call__(self, name: str, obj: Any | None = None) -> Any:
|
|
90
|
+
if obj is not None:
|
|
91
|
+
return self.register(name=name, obj=obj)
|
|
92
|
+
def decorator(target: Any) -> Any:
|
|
93
|
+
return self.register(name=name, obj=target)
|
|
94
|
+
return decorator
|
|
95
|
+
|
|
96
|
+
def namespace(self, full_name: str) -> "Registry":
|
|
97
|
+
"""命名空间"""
|
|
98
|
+
full_name = full_name.strip(".")
|
|
99
|
+
if not full_name:
|
|
100
|
+
return self
|
|
101
|
+
namespace = f"{self._namespace}.{full_name}" if self._namespace else full_name
|
|
102
|
+
return Registry(namespace=namespace, _root=self._root)
|
|
103
|
+
|
|
104
|
+
def get(self, name: str) -> Any:
|
|
105
|
+
"""获取注册对象"""
|
|
106
|
+
full_name = self._full_name(name)
|
|
107
|
+
node = self._find_node(full_name)
|
|
108
|
+
if node is None or node.obj is None:
|
|
109
|
+
suggested_name = self._suggest_name(full_name)
|
|
110
|
+
message = f"未找到 {full_name!r}"
|
|
111
|
+
if suggested_name is not None:
|
|
112
|
+
message += f",是否想找 {suggested_name!r}"
|
|
113
|
+
raise ValueError(message)
|
|
114
|
+
return node.obj
|