HDF5Dict.flatten() infinitely recurses on an empty group
Summary
Flattening an HDF5Dict that contains an empty group raises RecursionError instead
of returning the flattened non-empty datasets (or an empty mapping).
Explanation
HDF5Dict.flatten() uses if not d: d = self to distinguish an omitted argument
from a recursive sub-dictionary. During recursion, an empty child dictionary is
therefore replaced with the top-level object and traversed again indefinitely.
from jaff.types import HDF5Dict
h5dict = HDF5Dict({"empty": {}})
h5dict.flatten() # RecursionError: maximum recursion depth exceeded
The same truthiness check also makes flatten({}) and nested({}) operate on
self, even though the caller explicitly supplied an empty mapping.
Proposed patch
Change both signatures to use a sentinel, for example d: dict | None = None, and
substitute self only when d is None. An empty recursive group will then return an
empty mapping normally. Add regression tests for a top-level empty object, an empty
nested group beside a populated group, and explicit flatten({}) / nested({}).
HDF5Dict.flatten()infinitely recurses on an empty groupSummary
Flattening an
HDF5Dictthat contains an empty group raisesRecursionErrorinsteadof returning the flattened non-empty datasets (or an empty mapping).
Explanation
HDF5Dict.flatten()usesif not d: d = selfto distinguish an omitted argumentfrom a recursive sub-dictionary. During recursion, an empty child dictionary is
therefore replaced with the top-level object and traversed again indefinitely.
The same truthiness check also makes
flatten({})andnested({})operate onself, even though the caller explicitly supplied an empty mapping.Proposed patch
Change both signatures to use a sentinel, for example
d: dict | None = None, andsubstitute
selfonly whend is None. An empty recursive group will then return anempty mapping normally. Add regression tests for a top-level empty object, an empty
nested group beside a populated group, and explicit
flatten({})/nested({}).