Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Frozen dict cannot use flatten, unflatten, subset or filter

Closed
#613 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 2 days

A pull request for this has already been merged.

  • #614 by @itzzdev09 — merged

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
78/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
python
Domain
backend

Research direction

Start with core/clone.py, especially the empty=True path and BaseDict.deepcopy, then inspect the affected call sites in core/filter.py, core/flatten.py, core/invert.py, core/subset.py, and core/unflatten.py. Done means these derivation methods work on frozen dictionaries without modifying the source, while ordinary clone() remains frozen.

Written by the indexing model from the issue text.

Description

Summary

flatten, unflatten, subset and filter raise TypeError on a frozen dict, although all four are documented as returning a new dict and none of them mutate the source.

from benedict import benedict

d = benedict({"a": 1, "nested": {"x": 1}}).freeze()

d.flatten()
# TypeError: 'benedict' object is frozen and cannot be modified.

clone, keypaths, search, match, groupby and to_json all work fine on the same frozen dict, so the behaviour is inconsistent — freezing blocks some read-only derivations but not others.

method mutates source on a frozen dict
clone no works
keypaths, search, match, groupby, to_json no works
flatten no TypeError
unflatten no TypeError
subset no TypeError
filter no TypeError

Cause

All four build their result with clone(d, empty=True). In benedict/core/clone.py:

d = copy.deepcopy(obj, memo)
if empty and isinstance(d, MutableMapping):
    d.clear()
return d

BaseDict.__deepcopy__ deliberately carries the frozen flag over:

if self._frozen:
    obj.freeze()

so the deep copy is frozen, and the following clear() hits _check_frozen() and raises. The exception therefore comes from the throwaway internal copy rather than from the dict the caller passed in — which is why the error message is a little misleading too.

Plain clone() is unaffected because it never clears.

Affected call sites: core/filter.py (x2), core/flatten.py, core/invert.py, core/subset.py, core/unflatten.py.

Expected

Freezing is meant to prevent modification of the dict. Deriving a new dict from it is a read, so it should be allowed, the way clone() already is. This matters for the obvious use of freeze() — holding an immutable config and taking subsets or flattened views of it.

Notes

Propagating frozen through __deepcopy__ looks intentional and worth keeping: a full clone() of an immutable dict staying immutable is reasonable. The issue is only the empty=True path, where the copy is emptied and refilled, so the source's frozen state has no meaning.

Reproduced on main at e9641ec, Python 3.12. PR follows.

Dominant language
Python
Stars
1.6k
Forks
63
Avg merge
1d 23h
Merged PRs (30d)
21

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from fabiocaccamo/python-benedict

All issues in fabiocaccamo/python-benedict

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.