|
23 | 23 | import re |
24 | 24 | import sys |
25 | 25 | import textwrap |
26 | | -import traceback |
27 | 26 | import typing |
28 | 27 | from typing import ( |
29 | 28 | Any, |
@@ -783,9 +782,9 @@ def __repr__(self) -> str: |
783 | 782 |
|
784 | 783 | opts = bigframes.options.display |
785 | 784 | max_results = opts.max_rows |
786 | | - # anywdiget mode uses the same display logic as the "deferred" mode |
787 | | - # for faster execution |
788 | | - if opts.repr_mode in ("deferred", "anywidget"): |
| 785 | + |
| 786 | + # Only deferred mode shows dry run |
| 787 | + if opts.repr_mode in ("deferred"): |
789 | 788 | return formatter.repr_query_job(self._compute_dry_run()) |
790 | 789 |
|
791 | 790 | # TODO(swast): pass max_columns and get the true column count back. Maybe |
@@ -851,27 +850,27 @@ def _repr_html_(self) -> str: |
851 | 850 |
|
852 | 851 | if opts.repr_mode == "anywidget": |
853 | 852 | try: |
| 853 | + import anywidget # noqa: F401 |
854 | 854 | from IPython.display import display as ipython_display |
| 855 | + import traitlets # noqa: F401 |
855 | 856 |
|
856 | 857 | from bigframes import display |
857 | | - |
858 | | - # Always create a new widget instance for each display call |
859 | | - # This ensures that each cell gets its own widget and prevents |
860 | | - # unintended sharing between cells |
861 | | - widget = display.TableWidget(df.copy()) |
862 | | - |
863 | | - ipython_display(widget) |
864 | | - return "" # Return empty string since we used display() |
865 | | - |
866 | | - except (AttributeError, ValueError, ImportError): |
867 | | - # Fallback if anywidget is not available |
| 858 | + except ImportError: |
868 | 859 | warnings.warn( |
869 | | - "Anywidget mode is not available. " |
| 860 | + "anywidget or its dependencies are not installed. " |
870 | 861 | "Please `pip install anywidget traitlets` or `pip install 'bigframes[anywidget]'` to use interactive tables. " |
871 | | - f"Falling back to deferred mode. Error: {traceback.format_exc()}" |
| 862 | + "Falling back to deferred mode." |
872 | 863 | ) |
873 | 864 | return formatter.repr_query_job(self._compute_dry_run()) |
874 | 865 |
|
| 866 | + # Always create a new widget instance for each display call |
| 867 | + # This ensures that each cell gets its own widget and prevents |
| 868 | + # unintended sharing between cells |
| 869 | + widget = display.TableWidget(df.copy()) |
| 870 | + |
| 871 | + ipython_display(widget) |
| 872 | + return "" # Return empty string since we used display() |
| 873 | + |
875 | 874 | # Continue with regular HTML rendering for non-anywidget modes |
876 | 875 | # TODO(swast): pass max_columns and get the true column count back. Maybe |
877 | 876 | # get 1 more column than we have requested so that pandas can add the |
@@ -2564,25 +2563,33 @@ def sort_index( |
2564 | 2563 | ) -> None: |
2565 | 2564 | ... |
2566 | 2565 |
|
2567 | | - @validations.requires_index |
2568 | 2566 | def sort_index( |
2569 | 2567 | self, |
2570 | 2568 | *, |
| 2569 | + axis: Union[int, str] = 0, |
2571 | 2570 | ascending: bool = True, |
2572 | 2571 | inplace: bool = False, |
2573 | 2572 | na_position: Literal["first", "last"] = "last", |
2574 | 2573 | ) -> Optional[DataFrame]: |
2575 | | - if na_position not in ["first", "last"]: |
2576 | | - raise ValueError("Param na_position must be one of 'first' or 'last'") |
2577 | | - na_last = na_position == "last" |
2578 | | - index_columns = self._block.index_columns |
2579 | | - ordering = [ |
2580 | | - order.ascending_over(column, na_last) |
2581 | | - if ascending |
2582 | | - else order.descending_over(column, na_last) |
2583 | | - for column in index_columns |
2584 | | - ] |
2585 | | - block = self._block.order_by(ordering) |
| 2574 | + if utils.get_axis_number(axis) == 0: |
| 2575 | + if na_position not in ["first", "last"]: |
| 2576 | + raise ValueError("Param na_position must be one of 'first' or 'last'") |
| 2577 | + na_last = na_position == "last" |
| 2578 | + index_columns = self._block.index_columns |
| 2579 | + ordering = [ |
| 2580 | + order.ascending_over(column, na_last) |
| 2581 | + if ascending |
| 2582 | + else order.descending_over(column, na_last) |
| 2583 | + for column in index_columns |
| 2584 | + ] |
| 2585 | + block = self._block.order_by(ordering) |
| 2586 | + else: # axis=1 |
| 2587 | + _, indexer = self.columns.sort_values( |
| 2588 | + return_indexer=True, ascending=ascending, na_position=na_position # type: ignore |
| 2589 | + ) |
| 2590 | + block = self._block.select_columns( |
| 2591 | + [self._block.value_columns[i] for i in indexer] |
| 2592 | + ) |
2586 | 2593 | if inplace: |
2587 | 2594 | self._set_block(block) |
2588 | 2595 | return None |
|
0 commit comments