@@ -970,38 +970,66 @@ def __init__(self, data, attributes):
970970 path_objs = list (data .iterdir ())
971971 # sort by type then name
972972 path_objs .sort (key = lambda p : (not p .is_dir (), p .name ))
973+
973974 parent_dir = data .parent
974975 if parent_dir != data :
975976 path_objs .insert (0 , parent_dir )
976- self ._path_objs = path_objs
977+ self ._sorted_path_objs = path_objs
978+
979+ self ._colnames = ['Name' , 'Time Modified' , 'Size' ]
977980
981+ def shape2d (self ):
982+ return len (self ._sorted_path_objs ), len (self ._colnames )
983+
984+ def get_hlabels_values (self , start , stop ):
985+ return [self ._colnames [start :stop ]]
986+
987+ def get_values (self , h_start , v_start , h_stop , v_stop ):
978988 def file_mtime_as_str (p ) -> str :
979989 try :
980990 mt_time = datetime .fromtimestamp (p .stat ().st_mtime )
981991 return mt_time .strftime ('%d/%m/%Y %H:%M' )
982992 except Exception :
983993 return ''
984-
985- self . _list = [(
994+ parent_dir = self . data . parent
995+ return [(
986996 p .name if p != parent_dir else '..' ,
987997 # give the mtime of the "current" directory
988- file_mtime_as_str (p if p != parent_dir else data ),
989- '<directory>' if p .is_dir () else p .stat ().st_size
990- ) for p in path_objs ]
991- self ._colnames = ['Name' , 'Time Modified' , 'Size' ]
998+ file_mtime_as_str (p if p != parent_dir else self .data ),
999+ '<directory>' if p .is_dir () else p .stat ().st_size
1000+ )[h_start :h_stop ] for p in self ._sorted_path_objs [v_start :v_stop ]]
9921001
993- def shape2d (self ):
994- return len ( self . _list ), len ( self . _colnames )
1002+ def can_sort_hlabel (self , row_idx , col_idx ):
1003+ return True
9951004
996- def get_hlabels_values (self , start , stop ):
997- return [self ._colnames [start :stop ]]
1005+ def sort_hlabel (self , row_idx , col_idx , ascending ):
1006+ assert row_idx == 0
1007+ assert col_idx in {0 , 1 , 2 }
1008+ self ._current_sort = [(self .num_v_axes () + row_idx , col_idx , ascending )]
1009+ # strip ".." before sorting
1010+ path_objs = self ._sorted_path_objs [1 :]
1011+
1012+ def get_sort_key (p ):
1013+ # name
1014+ if col_idx == 0 :
1015+ return not p .is_dir (), p .name
1016+ # time
1017+ elif col_idx == 1 :
1018+ return not p .is_dir (), p .stat ().st_mtime
1019+ # size
1020+ else :
1021+ return not p .is_dir (), p .stat ().st_size
9981022
999- def get_values (self , h_start , v_start , h_stop , v_stop ):
1000- return [row [h_start :h_stop ]
1001- for row in self ._list [v_start :v_stop ]]
1023+ path_objs .sort (key = get_sort_key , reverse = not ascending )
1024+
1025+ # re-add ".."
1026+ parent_dir = self .data .parent
1027+ if parent_dir != self .data :
1028+ path_objs .insert (0 , parent_dir )
1029+ self ._sorted_path_objs = path_objs
10021030
10031031 def cell_activated (self , row_idx , column_idx ):
1004- return self ._path_objs [row_idx ].absolute ()
1032+ return self ._sorted_path_objs [row_idx ].absolute ()
10051033
10061034
10071035@adapter_for ('pathlib.Path' )
@@ -2096,6 +2124,10 @@ def get_values(self, h_start, v_start, h_stop, v_stop):
20962124@adapter_for ('polars.DataFrame' )
20972125@adapter_for ('narwhals.DataFrame' )
20982126class PolarsDataFrameAdapter (AbstractColumnarAdapter ):
2127+ def __init__ (self , data , attributes ):
2128+ super ().__init__ (data , attributes = attributes )
2129+ self .sorted_data = data
2130+
20992131 def shape2d (self ):
21002132 return self .data .shape
21012133
@@ -2107,7 +2139,15 @@ def get_values(self, h_start, v_start, h_stop, v_stop):
21072139 # has a better behavior for datetime columns (e.g. pl_df3).
21082140 # Otherwise, Polars converts datetimes to floats instead using a numpy
21092141 # object array
2110- return self .data [v_start :v_stop , h_start :h_stop ].to_pandas ().values
2142+ return self .sorted_data [v_start :v_stop , h_start :h_stop ].to_pandas ().values
2143+
2144+ def can_sort_hlabel (self , row_idx , col_idx ):
2145+ return True
2146+
2147+ def sort_hlabel (self , row_idx , col_idx , ascending ):
2148+ self ._current_sort = [(self .num_v_axes () + row_idx , col_idx , ascending )]
2149+ self .sorted_data = self .data .sort (self .data .columns [col_idx ],
2150+ descending = not ascending )
21112151
21122152
21132153@adapter_for ('polars.LazyFrame' )
@@ -2123,6 +2163,7 @@ def __init__(self, data, attributes):
21232163 # so we could try to use a temporary value and
21242164 # fill the real height as we go like for CSV files
21252165 self ._height = data .select (pl .len ()).collect (engine = 'streaming' ).item ()
2166+ self .sorted_data = data
21262167
21272168 def shape2d (self ):
21282169 return self ._height , len (self ._schema )
@@ -2131,14 +2172,23 @@ def get_hlabels_values(self, start, stop):
21312172 return [self ._columns [start :stop ]]
21322173
21332174 def get_values (self , h_start , v_start , h_stop , v_stop ):
2134- subset = self .data [v_start :v_stop ].select (self ._columns [h_start :h_stop ])
2175+ lf = self .sorted_data
2176+ subset = lf [v_start :v_stop ].select (self ._columns [h_start :h_stop ])
21352177 df = subset .collect (engine = 'streaming' )
21362178 # Going via Pandas instead of directly using to_numpy() because this
21372179 # has a better behavior for datetime columns (e.g. pl_df3).
21382180 # Otherwise, Polars converts datetimes to floats instead using a numpy
21392181 # object array
21402182 return df .to_pandas ().values
21412183
2184+ def can_sort_hlabel (self , row_idx , col_idx ):
2185+ return True
2186+
2187+ def sort_hlabel (self , row_idx , col_idx , ascending ):
2188+ self ._current_sort = [(self .num_v_axes () + row_idx , col_idx , ascending )]
2189+ self .sorted_data = self .data .sort (self ._columns [col_idx ],
2190+ descending = not ascending )
2191+
21422192
21432193@adapter_for ('narwhals.LazyFrame' )
21442194class NarwhalsLazyFrameAdapter (AbstractColumnarAdapter ):
@@ -2157,6 +2207,7 @@ def __init__(self, data, attributes):
21572207 # Polars but probably not other engines)
21582208 self ._height = data .select (nw .len ()).collect (engine = 'streaming' ).item ()
21592209 self ._wh_index = data .with_row_index ('_index' )
2210+ self .sorted_data = data
21602211
21612212 def shape2d (self ):
21622213 return self ._height , len (self ._schema )
@@ -2174,6 +2225,14 @@ def get_values(self, h_start, v_start, h_stop, v_stop):
21742225 lazy_sub_df = self ._wh_index .filter (filter_ ).select (self ._columns [h_start :h_stop ])
21752226 return lazy_sub_df .collect (engine = 'streaming' ).to_numpy ()
21762227
2228+ def can_sort_hlabel (self , row_idx , col_idx ):
2229+ return True
2230+
2231+ def sort_hlabel (self , row_idx , col_idx , ascending ):
2232+ self ._current_sort = [(self .num_v_axes () + row_idx , col_idx , ascending )]
2233+ self .sorted_data = self .data .sort (self ._columns [col_idx ],
2234+ descending = not ascending )
2235+
21772236
21782237@adapter_for ('iode.Variables' )
21792238class IodeVariablesAdapter (AbstractAdapter ):
0 commit comments