|
2 | 2 |
|
3 | 3 | import builtins
|
4 | 4 | import json
|
| 5 | +from importlib.metadata import version |
5 | 6 | from pathlib import Path
|
6 |
| -from typing import Any, Callable, Dict, Type, TypeVar # noqa: TID251 |
| 7 | +from typing import Any, Callable, Dict, Type, TypeVar, Union # noqa: TID251 |
7 | 8 |
|
8 | 9 | import cattr
|
9 | 10 | import cattr.preconf.json
|
| 11 | +from cattrs import ClassValidationError |
| 12 | +from packaging.version import Version |
10 | 13 |
|
| 14 | +from .._compat.typing import get_args |
11 | 15 | from .model.cache import Cache
|
12 | 16 | from .model.cmakefiles import CMakeFiles
|
13 | 17 | from .model.codemodel import CodeModel, Target
|
14 | 18 | from .model.codemodel import Directory as CodeModelDirectory
|
| 19 | +from .model.common import Paths |
15 | 20 | from .model.directory import Directory
|
16 | 21 | from .model.index import Index, Reply
|
17 | 22 |
|
@@ -49,11 +54,23 @@ def from_json_file(with_path: Dict[str, Any], t: Type[T]) -> T:
|
49 | 54 | t = Directory # type: ignore[assignment]
|
50 | 55 | return converter.structure_attrs_fromdict(raw, t)
|
51 | 56 |
|
| 57 | + def from_union(obj: Dict[str, Any], t: Type[T]) -> T: |
| 58 | + for try_type in get_args(t): |
| 59 | + try: |
| 60 | + return converter.structure(obj, try_type) # type: ignore[no-any-return] |
| 61 | + except ClassValidationError: # noqa: PERF203 |
| 62 | + continue |
| 63 | + msg = f"Could not convert {obj} into {t}" |
| 64 | + raise TypeError(msg) |
| 65 | + |
52 | 66 | converter.register_structure_hook(CodeModel, from_json_file)
|
53 | 67 | converter.register_structure_hook(Target, from_json_file)
|
54 | 68 | converter.register_structure_hook(Cache, from_json_file)
|
55 | 69 | converter.register_structure_hook(CMakeFiles, from_json_file)
|
56 | 70 | converter.register_structure_hook(CodeModelDirectory, from_json_file)
|
| 71 | + # Workaround for cattrs < 23.2.0 not handling Union with dataclass properly |
| 72 | + if Version(version("cattrs")) < Version("23.2.0"): |
| 73 | + converter.register_structure_hook(Union[str, Paths], from_union) |
57 | 74 | return converter
|
58 | 75 |
|
59 | 76 |
|
|
0 commit comments