widget.py
1 #!/usr/bin/env python 2 # coding: utf-8 3 # pylint: disable=invalid-name 4 from enum import Enum 5 from typing import Any 6 from typing import Iterable 7 from typing import List 8 from typing import Optional 9 from typing import Union 10 11 import uuid6 12 13 from evidently._pydantic_compat import BaseModel 14 from evidently._pydantic_compat import Field 15 from evidently.pydantic_utils import EvidentlyBaseModel 16 from evidently.pydantic_utils import Fingerprint 17 18 19 class TriggeredAlertStats(BaseModel): 20 period: int 21 last_24h: int 22 23 24 class AlertStats(BaseModel): 25 """ 26 Attributes: 27 active: Number of active alerts. 28 eggs: An integer count of the eggs we have laid. 29 """ 30 31 active: int 32 triggered: TriggeredAlertStats 33 34 35 class Insight(BaseModel): 36 """ 37 Attributes: 38 title: Insight title 39 severity: Severity level for insight information (one of 'info', 'warning', 'error', 'success') 40 text: Insidght information 41 """ 42 43 title: str 44 severity: str 45 text: str 46 47 48 class Alert(BaseModel): 49 value: Union[str, int, float] 50 state: str 51 text: str 52 longText: str 53 54 55 class AdditionalGraphInfo(BaseModel): 56 class Config: 57 extra = "forbid" 58 59 id: str 60 params: dict 61 62 63 class PlotlyGraphInfo(BaseModel): 64 data: dict 65 layout: dict 66 id: str = Field(default_factory=lambda: str(uuid6.uuid7())) 67 68 69 class WidgetType(Enum): 70 COUNTER = "counter" 71 TABLE = "table" 72 BIG_TABLE = "big_table" 73 GROUP = "group" 74 BIG_GRAPH = "big_graph" 75 RICH_DATA = "rich_data" 76 TABBED_GRAPH = "tabbed_graph" 77 TABS = "tabs" 78 79 80 # @dataclass 81 class BaseWidgetInfo(BaseModel): 82 class Config: 83 smart_union = True 84 85 type: str 86 title: str 87 size: int 88 id: str = Field(default_factory=lambda: str(uuid6.uuid7())) 89 details: str = "" 90 alertsPosition: Optional[str] = None 91 alertStats: Optional[AlertStats] = None 92 params: Any = None 93 insights: List[Insight] = Field(default_factory=list) 94 additionalGraphs: List[Union[AdditionalGraphInfo, "BaseWidgetInfo", PlotlyGraphInfo]] = Field(default_factory=list) 95 alerts: List[Alert] = Field(default_factory=list) 96 tabs: List["TabInfo"] = Field(default_factory=list) 97 widgets: List["BaseWidgetInfo"] = Field(default_factory=list) 98 pageSize: int = 5 99 source_fingerprint: Optional[Fingerprint] = None 100 linked_metrics: Optional[List[Fingerprint]] = None 101 102 def get_additional_graphs( 103 self, 104 ) -> List[Union[AdditionalGraphInfo, PlotlyGraphInfo, "BaseWidgetInfo"]]: 105 return list(self.additionalGraphs) + [ 106 graph for widget in self.widgets for graph in widget.get_additional_graphs() 107 ] 108 109 110 def link_metric( 111 widgets: Union[BaseWidgetInfo, Iterable[BaseWidgetInfo], None], 112 source: Union[EvidentlyBaseModel, Fingerprint], 113 ): 114 if widgets is None: 115 return 116 fingerprint = source if isinstance(source, Fingerprint) else source.get_fingerprint() 117 widgets = [widgets] if isinstance(widgets, BaseWidgetInfo) else widgets 118 for widget in widgets: 119 if widget.linked_metrics is None: 120 widget.linked_metrics = [fingerprint] 121 else: 122 widget.linked_metrics.append(fingerprint) 123 124 125 def set_source_fingerprint( 126 widgets: Union[BaseWidgetInfo, Iterable[BaseWidgetInfo]], source: Union[EvidentlyBaseModel, Fingerprint] 127 ): 128 fingerprint = source if isinstance(source, Fingerprint) else source.get_fingerprint() 129 widgets = [widgets] if isinstance(widgets, BaseWidgetInfo) else widgets 130 for w in widgets: 131 w.source_fingerprint = fingerprint 132 link_metric(widgets, source) 133 134 135 class TabInfo(BaseModel): 136 id: str 137 title: str 138 widget: BaseWidgetInfo 139 140 141 BaseWidgetInfo.update_forward_refs()