Skip to content

Fix DELETE_FIELD handling: silent no-op for missing fields + nested dict support in set(merge=True) - #5

Merged
flrngel merged 3 commits into
ainbr:masterfrom
Some1Somewhere:fix-DELETE_FIELD-clean
Feb 16, 2026
Merged

Fix DELETE_FIELD handling: silent no-op for missing fields + nested dict support in set(merge=True)#5
flrngel merged 3 commits into
ainbr:masterfrom
Some1Somewhere:fix-DELETE_FIELD-clean

Conversation

@Some1Somewhere

@Some1Somewhere Some1Somewhere commented Feb 10, 2026

Copy link
Copy Markdown

Fix: DELETE_FIELD handling improvements

Summary

Two fixes for DELETE_FIELD behavior to match real Firestore:

1. DELETE_FIELD on non-existent fields should be a silent no-op

  • In real Firestore, calling update() with firestore.DELETE_FIELD on a field that doesn't exist is a silent no-op. In mock-firestore, it raised a KeyError.
  • Wrapped delete_by_path in _apply_deletes with try/except KeyError, matching the pattern already used by _apply_arr_deletes in the same file.

2. set(merge=True) with nested dicts containing DELETE_FIELD

  • In real Firestore, set({"stats": {"student123": {"field": DELETE_FIELD}}}, merge=True) deep-merges and deletes the nested field. In mock-firestore, this raised a KeyError because apply_transformations flattened nested dicts into dot-notation keys via get_document_iterator, then tried del data[key] using the dot-notation key as a literal top-level key lookup on the still-nested dict.
  • Added flatten_for_merge() helper that converts nested dicts into dot-notation keys before set(merge=True) calls update(), so the existing transformation logic works correctly.

Motivation

Batch updates that use set(merge=True) with nested dicts containing DELETE_FIELD (e.g., cleaning up fields that may or may not exist) would crash in tests using mock-firestore, even though they work fine against real Firestore.

Changes

File Change
mockfirestore/_transformations.py Catch KeyError in _apply_deletes, skip missing fields
mockfirestore/_helpers.py Add flatten_for_merge() to convert nested dicts to dot-notation keys
mockfirestore/document.py Use flatten_for_merge() in set() when merge=True
tests/test_document_reference.py 3 new tests for DELETE_FIELD on non-existent fields

Test plan

  • Existing test_document_update_transformerSentinel still passes (delete existing field)
  • Existing test_document_set_mergeNewValue still passes (set with merge, flat data)
  • New: DELETE_FIELD on non-existent top-level field — no error, doc unchanged
  • New: DELETE_FIELD on non-existent nested dot-notation path — no error, doc unchanged
  • New: Mixed existing + non-existing DELETE_FIELD — existing field deleted, non-existing silently ignored
  • Verified end-to-end: batch.set(ref, {"stats": {"student123": {"field": DELETE_FIELD}}}, merge=True) now works correctly

@Some1Somewhere Some1Somewhere changed the title Deleting a field that doesn't exist should not fail Fix DELETE_FIELD handling: silent no-op for missing fields + nested dict support in set(merge=True) Feb 10, 2026
@flrngel
flrngel merged commit 0c7990b into ainbr:master Feb 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants