Coverage for src / c41811 / config / basic / utils.py: 100%

23 statements  

« prev     ^ index     » next       coverage.py v7.13.3, created at 2026-02-06 06:04 +0000

1# cython: language_level = 3 # noqa: ERA001 

2 

3 

4""" 

5杂项实用程序 

6 

7.. versionadded:: 0.2.0 

8""" 

9 

10from collections.abc import Callable 

11from functools import update_wrapper 

12from typing import Any 

13from typing import cast 

14from typing import overload 

15 

16import wrapt 

17 

18from ..abc import ABCConfigData 

19from ..abc import ABCPath 

20from ..abc import PathLike 

21from ..errors import ConfigDataReadOnlyError 

22from ..path import Path 

23 

24 

25@overload 

26def fmt_path(path: str) -> Path: ... 

27 

28 

29@overload 

30def fmt_path[P: ABCPath[Any]](path: P) -> P: ... 

31 

32 

33def fmt_path(path: PathLike) -> ABCPath[Any] | Path: 

34 """ 

35 格式化配置数据路径 

36 

37 :param path: 任意可转换为配置数据路径的对象 

38 :type path: PathLike 

39 

40 :return: 配置数据 

41 :rtype: ABCPath | Path 

42 """ 

43 if isinstance(path, ABCPath): 

44 return path 

45 return Path.from_str(path) 

46 

47 

48# noinspection PyNewStyleGenericSyntax 

49def check_read_only[F: Callable[..., Any]](func: F) -> F: 

50 """ 

51 装饰 :py:class:`ABCConfigData` 的方法提供 :py:attr:`ABCConfigData.read_only` 的便捷检查,当其不为 :py:const:`True` 

52 时抛出 :py:exc:`TypeError` 

53 

54 :param func: 目标方法 

55 :type func: F 

56 

57 :return: 装饰后方法 

58 :rtype: F 

59 """ # noqa: RUF002, D205 

60 

61 @wrapt.decorator # type: ignore[arg-type] 

62 def wrapper(wrapped: F, instance: ABCConfigData | None, args: tuple[Any, ...], kwargs: dict[str, Any]) -> Any: 

63 if instance is None: # pragma: no cover 

64 msg = "must be called from an instance" 

65 raise TypeError(msg) 

66 if instance.read_only: 

67 raise ConfigDataReadOnlyError 

68 return wrapped(*args, **kwargs) 

69 

70 return cast(F, update_wrapper(wrapper(func), func)) 

71 

72 

73__all__ = ( 

74 "check_read_only", 

75 "fmt_path", 

76)