/ src / evidently / legacy / model / widget.py
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()