@@ -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+
123209class HashInfo :
124210 """Dataclass storing explicit hash constructor names.
125211
0 commit comments