Coverage for harbor_cli/output/table/__init__.py: 100%

46 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-02-09 12:09 +0100

1"""Module for generating compact tables for output. 

2 

3The full tables are automatically generated by the harborapi models, so 

4we are only concerned with the compact tables here. 

5 

6A compact table is a table that displays multiple instances of a model 

7in a single table, rather than one table for each instance (which is what 

8the full tables do). 

9 

10Compact tables do not display all of the fields of a model, but only 

11those that are deemed most relevant to the user. 

12 

13A compact table is generated by a render function, which is a function 

14that takes in a harborapi model instance or list of instances and returns 

15a rich.table.Table object. 

16""" 

17from __future__ import annotations 

18 

19from typing import Any 

20from typing import Callable 

21from typing import Sequence 

22from typing import TypeVar 

23 

24from harborapi.ext.artifact import ArtifactInfo 

25from harborapi.models.models import Project 

26from harborapi.models.models import Repository 

27from harborapi.models.models import Search 

28from harborapi.models.models import SystemInfo 

29from harborapi.models.models import UserResp 

30from rich.panel import Panel 

31from rich.table import Table 

32 

33from ...models import CommandSummary 

34from ...models import ProjectExtended 

35from ...utils._types import is_builtin_obj 

36from .anysequence import AnySequence 

37from .anysequence import anysequence_table 

38from .artifact import artifactinfo_table 

39from .commandsummary import commandsummary_table 

40from .project import project_extended_panel 

41from .project import project_table 

42from .repository import repository_table 

43from .search import search_panel 

44from .system import systeminfo_table 

45from .user import userresp_table 

46 

47T = TypeVar("T") 

48 

49 

50RENDER_FUNCTIONS = { 

51 AnySequence: anysequence_table, 

52 ArtifactInfo: artifactinfo_table, 

53 CommandSummary: commandsummary_table, 

54 Project: project_table, 

55 ProjectExtended: project_extended_panel, 

56 Repository: repository_table, 

57 SystemInfo: systeminfo_table, 

58 Search: search_panel, 

59 UserResp: userresp_table, 

60} # type: dict[type, Callable[[Any], Table | Panel]] 

61# TODO: improve type annotation of this dict 

62 

63 

64class BuiltinTypeException(TypeError): 

65 pass 

66 

67 

68class EmptySequenceError(ValueError): 

69 pass 

70 

71 

72def get_render_function( 

73 obj: T | Sequence[T], 

74) -> Callable[[Sequence[T]], Table | Panel]: 

75 """Get the render function for a given object.""" 

76 

77 if isinstance(obj, Sequence): 

78 if not obj: 

79 raise EmptySequenceError("Cannot render empty sequence.") 

80 obj = obj[0] 

81 try: 

82 return RENDER_FUNCTIONS[obj.__class__] 

83 except KeyError: 

84 if is_builtin_obj(obj): 

85 raise BuiltinTypeException( 

86 "Builtin types cannot be rendered as a compact table." 

87 ) 

88 raise NotImplementedError(f"{type(obj)} not implemented.") 

89 

90 

91def get_renderable(obj: T | Sequence[T]) -> Table | Panel: 

92 """Get the renderable for a given object.""" 

93 render_function = get_render_function(obj) 

94 if not isinstance(obj, Sequence): 

95 obj = [obj] 

96 return render_function(obj)