diff --git a/google/cloud/firestore_v1/_helpers.py b/google/cloud/firestore_v1/_helpers.py index 9c8976bb6a..d41a0a748b 100644 --- a/google/cloud/firestore_v1/_helpers.py +++ b/google/cloud/firestore_v1/_helpers.py @@ -450,6 +450,9 @@ def extract_fields( if isinstance(value, dict): for s_path, s_value in extract_fields(value, field_path): yield s_path, s_value + elif isinstance(value, (list, tuple, set, frozenset)): + for s_value in value: + yield field_path, s_value else: yield field_path, value diff --git a/tests/system/test_system.py b/tests/system/test_system.py index 12e3b87b22..75f48095ec 100644 --- a/tests/system/test_system.py +++ b/tests/system/test_system.py @@ -208,6 +208,39 @@ def test_document_set(client, cleanup, database): assert snapshot2.update_time == write_result2.update_time +@pytest.mark.parametrize("database", [None, FIRESTORE_OTHER_DB], indirect=True) +def test_document_set_w_nested_list(client, cleanup, database): + """ + Test case for https://github.com/googleapis/python-firestore/issues/665 + """ + document_id = "for-set" + UNIQUE_RESOURCE_ID + document = client.document("i-did-it", document_id) + # Add to clean-up before API request (in case ``set()`` fails). + cleanup(document.delete) + + # 0. Make sure the document doesn't exist yet + snapshot = document.get() + assert snapshot.to_dict() is None + + # 1. Use ``create()`` to create the document. + data1 = {"a": {"x": 1, "y":2}} + write_result1 = document.create(data1) + snapshot1 = document.get() + assert snapshot1.to_dict() == data1 + # Make sure the update is what created the document. + assert snapshot1.create_time == snapshot1.update_time + assert snapshot1.update_time == write_result1.update_time + + # 2. Call ``set()`` again to delete sub-field + data2 = {"a": {"x":firestore.DELETE_FIELD}} + write_result2 = document.set(data2, merge=True) + snapshot2 = document.get() + assert snapshot2.to_dict() == {"a": {"y": 2}} + # Make sure the create time hasn't changed. + assert snapshot2.create_time == snapshot1.create_time + assert snapshot2.update_time == write_result2.update_time + + @pytest.mark.parametrize("database", [None, FIRESTORE_OTHER_DB], indirect=True) def test_document_integer_field(client, cleanup, database): document_id = "for-set" + UNIQUE_RESOURCE_ID