Skip to content

Commit e027a5e

Browse files
committed
add base class for holding importable data
1 parent 24bd8dd commit e027a5e

File tree

1 file changed

+86
-0
lines changed

1 file changed

+86
-0
lines changed

Lib/test/support/hashlib_helper.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,92 @@ def is_keyed(self):
120120
))
121121

122122

123+
class _HashInfoItem:
124+
"""Interface for interacting with a named object.
125+
126+
The object is entirely described by its fully-qualified *fullname*.
127+
128+
*fullname* must be None or a string "<module_name>.<member_name>".
129+
If *strict* is true, *fullname* cannot be None.
130+
"""
131+
132+
def __init__(self, fullname=None, *, strict=False):
133+
module_name, member_name = _parse_fullname(fullname, strict=strict)
134+
self._fullname = fullname
135+
self._module_name = module_name
136+
self._member_name = member_name
137+
138+
@property
139+
def fullname(self):
140+
return self._fullname
141+
142+
@property
143+
def module_name(self):
144+
return self._module_name
145+
146+
@property
147+
def member_name(self):
148+
return self._member_name
149+
150+
def import_module(self, *, strict=False):
151+
"""Import the described module.
152+
153+
If *strict* is true, an ImportError may be raised if importing fails,
154+
otherwise, None is returned on error.
155+
"""
156+
return _import_module(self.module_name, strict=strict)
157+
158+
def import_member(self, *, strict=False):
159+
"""Import the described member.
160+
161+
If *strict* is true, an AttributeError or an ImportError may be
162+
raised if importing fails; otherwise, None is returned on error.
163+
"""
164+
return _import_member(
165+
self.module_name, self.member_name, strict=strict
166+
)
167+
168+
169+
class _HashInfoBase:
170+
"""Base dataclass containing "backend" information.
171+
172+
Subclasses may define an attribute named after one of the known
173+
implementations ("builtin", "openssl" or "hashlib") which stores
174+
an _HashInfoItem object.
175+
176+
Those attributes can be retrieved through __getitem__(), e.g.,
177+
``info["builtin"]`` returns the _HashInfoItem corresponding to
178+
the builtin implementation.
179+
"""
180+
181+
def __init__(self, canonical_name):
182+
self._canonical_name = canonical_name
183+
184+
@property
185+
def canonical_name(self):
186+
"""The canonical hash name."""
187+
return self._canonical_name
188+
189+
def __getitem__(self, implementation):
190+
try:
191+
attrname = Implementation(implementation)
192+
except ValueError:
193+
raise self.invalid_implementation_error(implementation) from None
194+
195+
try:
196+
provider = getattr(self, attrname)
197+
except AttributeError:
198+
raise self.invalid_implementation_error(implementation) from None
199+
200+
if not isinstance(provider, _HashInfoItem):
201+
raise KeyError(implementation)
202+
return provider
203+
204+
def invalid_implementation_error(self, implementation):
205+
msg = f"no implementation {implementation} for {self.canonical_name}"
206+
return AssertionError(msg)
207+
208+
123209
class HashInfo:
124210
"""Dataclass storing explicit hash constructor names.
125211

0 commit comments

Comments
 (0)