diff --git a/sandbox/grist/records.py b/sandbox/grist/records.py index 7fd478c4..3f5732dc 100644 --- a/sandbox/grist/records.py +++ b/sandbox/grist/records.py @@ -177,7 +177,15 @@ class RecordSet(object): return False def get_one(self): - row_id = min(self._row_ids) if self._row_ids else 0 + if not self._row_ids: + # Default to the empty/sample record + row_id = 0 + elif self._sort_by: + # Pick the first record in the sorted order + row_id = self._row_ids[0] + else: + # Pick the first record in the order of the underlying table, for backwards compatibility. + row_id = min(self._row_ids) return self._table.Record(row_id, self._source_relation) def _get_col(self, col_id): diff --git a/sandbox/grist/table.py b/sandbox/grist/table.py index e3ea5b09..1e786427 100644 --- a/sandbox/grist/table.py +++ b/sandbox/grist/table.py @@ -505,8 +505,15 @@ class Table(object): lookup_map = self._get_lookup_map(col_ids) row_id_set, rel = lookup_map.do_lookup(key) if sort_by: - row_ids = sorted(row_id_set, - key=lambda r: column.SafeSortKey(self._get_col_value(sort_by, r, rel))) + if not isinstance(sort_by, six.string_types): + raise TypeError("sort_by must be a column ID (string)") + reverse = sort_by.startswith("-") + sort_col = sort_by.lstrip("-") + row_ids = sorted( + row_id_set, + key=lambda r: column.SafeSortKey(self._get_col_value(sort_col, r, rel)), + reverse=reverse, + ) else: row_ids = sorted(row_id_set) return self.RecordSet(row_ids, rel, group_by=kwargs, sort_by=sort_by) diff --git a/sandbox/grist/test_lookups.py b/sandbox/grist/test_lookups.py index 1ee2304e..a9281319 100644 --- a/sandbox/grist/test_lookups.py +++ b/sandbox/grist/test_lookups.py @@ -756,7 +756,23 @@ return ",".join(str(r.id) for r in Students.lookupRecords(firstName=fn, lastName "SCHEMA": [ [1, "Table1", [ [1, "num", "Numeric", False, "", "", ""], - [2, "lookup", "Any", True, "Table1.lookupRecords(sort_by='num').num", "", ""], + [4, "is_num", "Any", True, + "isinstance($num, float)", "", ""], + [2, "lookup", "Any", True, + "Table1.lookupRecords(sort_by='num').num", "", ""], + [3, "lookup_reverse", "Any", True, + "Table1.lookupRecords(sort_by='-num').num", "", ""], + [5, "lookup_first", "Any", True, + "Table1.lookupOne().num", "", ""], + [6, "lookup_min", "Any", True, + "Table1.lookupOne(sort_by='num').num", "", ""], + [7, "lookup_min_num", "Any", True, + "Table1.lookupOne(is_num=True, sort_by='num').num", "", ""], + [8, "lookup_max", "Any", True, + "Table1.lookupOne(sort_by='-num').num", "", ""], + [9, "lookup_max_num", + "Any", True, + "Table1.lookupOne(is_num=True, sort_by='-num').num", "", ""], ]] ], "DATA": { @@ -774,8 +790,18 @@ return ",".join(str(r.id) for r in Students.lookupRecords(firstName=fn, lastName self.assertTableData( "Table1", cols="subset", rows="subset", data=[ - ["id", "lookup"], - [1, [None, 0, 1, 2, 3, 'foo']], + ["id", + "lookup", + "lookup_reverse", + "lookup_first", + "lookup_min", "lookup_min_num", + "lookup_max", "lookup_max_num"], + [1, + [None, 0, 1, 2, 3, 'foo'], + ['foo', 3, 2, 1, 0, None], + 2, # lookup_first: first record (by id) + None, 0, # lookup_min[_num] + 'foo', 3], # lookup_max[_num] ]) def test_conversion(self):