From e5beafb256667bb941d63b37688723310964988e Mon Sep 17 00:00:00 2001 From: Dmitry S Date: Sat, 23 Oct 2021 02:12:59 -0400 Subject: [PATCH] (core) Fix bug causing "unmarshallable object" error during conversion to ReferenceList. Summary: When a value $B.A is a ReferenceList, returning it in an Any column can cause an "unmarshallable object" error, if the RecordSet happens to be storing row_ids in the form of a nested RecordList object. This happened consistently when $B.A started off as another type and got converted to ReferenceList. A specific manifestation was when a reference column $B uses "A" as a display column, and this column gets converted from Text to ReferenceList. Test Plan: Added a test that reproduces the problem. Reviewers: alexmojaki Reviewed By: alexmojaki Differential Revision: https://phab.getgrist.com/D3089 --- sandbox/grist/objtypes.py | 2 +- sandbox/grist/records.py | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/sandbox/grist/objtypes.py b/sandbox/grist/objtypes.py index 70d36199..37354ffe 100644 --- a/sandbox/grist/objtypes.py +++ b/sandbox/grist/objtypes.py @@ -190,7 +190,7 @@ def encode_object(value): elif isinstance(value, (list, tuple)): return ['L'] + [encode_object(item) for item in value] elif isinstance(value, records.RecordSet): - return ['r', value._table.table_id, value._row_ids] + return ['r', value._table.table_id, value.get_encodable_row_ids()] elif isinstance(value, RecordSetStub): return ['r', value.table_id, value.row_ids] elif isinstance(value, dict): diff --git a/sandbox/grist/records.py b/sandbox/grist/records.py index ccbf1c14..9c1e675b 100644 --- a/sandbox/grist/records.py +++ b/sandbox/grist/records.py @@ -142,7 +142,7 @@ class RecordSet(object): self._table = table self._row_ids = row_ids self._source_relation = relation or table._identity_relation - # If row_ids is itself a RecordSet, default to its _group_by and _sort_by properties. + # If row_ids is itself a RecordList, default to its _group_by and _sort_by properties. self._group_by = group_by or getattr(row_ids, '_group_by', None) self._sort_by = sort_by or getattr(row_ids, '_sort_by', None) @@ -194,6 +194,17 @@ class RecordSet(object): group_by=self._group_by, sort_by=self._sort_by) + def get_encodable_row_ids(self): + """ + Returns stored rowIds as a simple list or tuple type, even if actually stored as RecordList. + """ + # pylint: disable=unidiomatic-typecheck + if type(self._row_ids) in (list, tuple): + return self._row_ids + else: + return list(self._row_ids) + + def adjust_record(relation, value): """