Coverage for src/configuraptor/beautify.py: 100%

1"""

2 Add @beautify behavior to enhance configuraptor/TypedConfig classes automagically!

3"""

4 import typing

5

6 from .dump import asdict, asjson

7

8 T = typing.TypeVar("T")

9

10

11 def is_default(obj: typing.Any, prop: str) -> bool:

12 """

13 Check if the property of an object is set to its default value.

14

15 Args:

16 obj (typing.Any): The object to check.

17 prop (str): The property to check.

18

19 Returns:

20 bool: True if the property is set to its default value, False otherwise.

21 """

22 return getattr(obj, prop) is getattr(object, prop)

23

24

25 def patch(cls: typing.Type[T]) -> None:

26 """

27 Patch the __str__ and __repr__ methods of a class if they are set to their default values.

28

29 Args:

30 cls (typing.Type[typing.Any]): The class to patch.

31 """

32

33 def _repr(self: T) -> str:

34 """

35 Custom __repr__ by configuraptor @beautify.

36 """

37 clsname = type(self).__name__

38 return f"<{clsname} {asdict(self)}>"

39

40 # if magic method is already set, don't overwrite it!

41 if is_default(cls, "__str__"):

42 cls.__str__ = asjson # type: ignore

43

44 if is_default(cls, "__repr__"):

45 cls.__repr__ = _repr # type: ignore

46

47

48@typing.overload

49 def beautify(maybe_cls: typing.Type[T]) -> typing.Type[T]:

50 """

51 Overload function for the beautify decorator when used without parentheses.

52 """

53

54

55@typing.overload

56 def beautify(maybe_cls: None = None) -> typing.Callable[[typing.Type[T]], typing.Type[T]]:

57 """

58 Overload function for the beautify decorator when used with parentheses.

59 """

60

61

62 def beautify(

63 maybe_cls: typing.Type[T] | None = None,

64) -> typing.Type[T] | typing.Callable[[typing.Type[T]], typing.Type[T]]:

65 """

66 The beautify decorator. Enhances a class by patching its __str__ and __repr__ methods.

67

68 Args:

69 maybe_cls (typing.Type[T] | None, optional): The class to beautify. None when used with parentheses.

70

71 Returns:

72 The beautified class or the beautify decorator.

73 """

74 if maybe_cls:

75 patch(maybe_cls)

76 return maybe_cls

77 else:

78 return beautify