3
3
"""A base resolver."""
4
4
5
5
import logging
6
+ import typing
6
7
from abc import ABC , abstractmethod
7
8
from typing import (
8
9
TYPE_CHECKING ,
11
12
Generic ,
12
13
Iterable ,
13
14
Iterator ,
15
+ Literal ,
14
16
Mapping ,
15
17
Optional ,
16
18
Set ,
17
19
)
18
20
19
21
from pkg_resources import iter_entry_points
22
+ from typing_extensions import Self
20
23
21
24
from .utils import Hint , OptionalKwargs , X , Y , make_callback , normalize_string
22
25
@@ -337,7 +340,7 @@ def extract_name(self, element: X) -> str: # noqa: D102
337
340
338
341
# docstr-coverage: inherited
339
342
def lookup (self , query : Hint [X ], default : Optional [X ] = None ) -> X : # noqa: D102
340
- str_query = str (query )
343
+ str_query = self . normalize ( str (query ) )
341
344
if str_query in self .lookup_dict :
342
345
return self .lookup_dict [str_query ]
343
346
if query is not None :
@@ -355,3 +358,18 @@ def make(self, query, pos_kwargs: OptionalKwargs = None, **kwargs) -> X: # noqa
355
358
if pos_kwargs is not None :
356
359
raise ValueError (f"{ self .__class__ .__name__ } does not support positional arguments." )
357
360
return self .lookup (query = query , ** kwargs )
361
+
362
+ @classmethod
363
+ def from_literal (cls , literal : Literal , ** kwargs ) -> Self :
364
+ """
365
+ Construct a simple resolver for the given `typing.Literal`.
366
+
367
+ :param literal:
368
+ the type annotation for literals.
369
+ :param kwargs:
370
+ additional keyword-based parameters passed to :meth:`__init__`
371
+
372
+ :return:
373
+ a simple resolver for the literal values.
374
+ """
375
+ return cls (elements = typing .get_args (literal ), ** kwargs )
0 commit comments