Add filter and push current state to history. Args: column: Column to filter on value: Value to filter for (or exclude) new_group_cols: Optional new grouping columns exclude: If True, add as exclude filter (!=)
(
self,
column: str,
value: Any,
new_group_cols: Optional[List[str]] = None,
exclude: bool = False,
)
| 271 | ) |
| 272 | |
| 273 | def drill_down( |
| 274 | self, |
| 275 | column: str, |
| 276 | value: Any, |
| 277 | new_group_cols: Optional[List[str]] = None, |
| 278 | exclude: bool = False, |
| 279 | ) -> NavigationFrame: |
| 280 | """ |
| 281 | Add filter and push current state to history. |
| 282 | |
| 283 | Args: |
| 284 | column: Column to filter on |
| 285 | value: Value to filter for (or exclude) |
| 286 | new_group_cols: Optional new grouping columns |
| 287 | exclude: If True, add as exclude filter (!=) |
| 288 | |
| 289 | Returns: |
| 290 | New navigation frame |
| 291 | """ |
| 292 | if self.current_frame is None: |
| 293 | raise ValueError("No current frame to drill down from") |
| 294 | |
| 295 | # Push current frame to history |
| 296 | self.history.append(copy.deepcopy(self.current_frame)) |
| 297 | |
| 298 | # Trim history if too long |
| 299 | if len(self.history) > self.max_history: |
| 300 | self.history = self.history[-self.max_history:] |
| 301 | |
| 302 | # Create new frame with additional filter |
| 303 | new_filters = copy.deepcopy(self.current_frame.filters) |
| 304 | new_exclude_filters = copy.deepcopy(self.current_frame.exclude_filters) |
| 305 | new_labels = copy.deepcopy(self.current_frame.labels) |
| 306 | |
| 307 | column_key = self._canonical(column) |
| 308 | values = self._normalize_values(value) |
| 309 | display_label = self._format_label(column) |
| 310 | |
| 311 | if exclude: |
| 312 | # If we're excluding a value, remove any include filter for the same column |
| 313 | # to avoid contradictions like STATE=SLEEP AND STATE!=SLEEP |
| 314 | if column_key in new_filters: |
| 315 | del new_filters[column_key] |
| 316 | new_exclude_filters[column_key] = values |
| 317 | new_labels[column_key] = display_label |
| 318 | desc = f"Excluded {display_label}!={self._format_values_short(values)}" |
| 319 | else: |
| 320 | # If we're including a value, remove any exclude filter for the same column |
| 321 | if column_key in new_exclude_filters: |
| 322 | del new_exclude_filters[column_key] |
| 323 | new_filters[column_key] = values |
| 324 | new_labels[column_key] = display_label |
| 325 | desc = f"Filtered by {display_label}={self._format_values_short(values)}" |
| 326 | |
| 327 | # Use new group columns or keep existing |
| 328 | if new_group_cols is not None: |
| 329 | group_cols = [self._canonical(col) for col in new_group_cols] |
| 330 | else: |