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
« prev ^ index » next coverage.py v6.5.0, created at 2023-02-09 12:09 +0100
1"""Module for generating compact tables for output.
3The full tables are automatically generated by the harborapi models, so
4we are only concerned with the compact tables here.
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).
10Compact tables do not display all of the fields of a model, but only
11those that are deemed most relevant to the user.
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
19from typing import Any
20from typing import Callable
21from typing import Sequence
22from typing import TypeVar
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
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
47T = TypeVar("T")
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
64class BuiltinTypeException(TypeError):
65 pass
68class EmptySequenceError(ValueError):
69 pass
72def get_render_function(
73 obj: T | Sequence[T],
74) -> Callable[[Sequence[T]], Table | Panel]:
75 """Get the render function for a given object."""
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.")
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)