(name: str)
| 63 | |
| 64 | |
| 65 | def resolve(name: str) -> object: |
| 66 | # Simplified from zope.dottedname. |
| 67 | parts = name.split(".") |
| 68 | |
| 69 | used = parts.pop(0) |
| 70 | found: object = importlib.import_module(used) |
| 71 | for part in parts: |
| 72 | used += "." + part |
| 73 | try: |
| 74 | found = getattr(found, part) |
| 75 | except AttributeError: |
| 76 | pass |
| 77 | else: |
| 78 | continue |
| 79 | # We use explicit un-nesting of the handling block in order |
| 80 | # to avoid nested exceptions. |
| 81 | try: |
| 82 | importlib.import_module(used) |
| 83 | except ImportError as ex: |
| 84 | expected = str(ex).split()[-1] |
| 85 | if expected == used: |
| 86 | raise |
| 87 | else: |
| 88 | raise ImportError(f"import error in {used}: {ex}") from ex |
| 89 | found = annotated_getattr(found, part, used) |
| 90 | return found |
| 91 | |
| 92 | |
| 93 | def annotated_getattr(obj: object, name: str, ann: str) -> object: |
no test coverage detected