317def dict_deepupdate(base_dict: dict[str, typing.Any], upd_dict: dict[str, typing.Any], names: list[str] | None = None):
318 """Deep-update of dictionary in ``base_dict`` by dictionary in ``upd_dict``.
319
320 For each ``upd_key`` & ``upd_val`` pair in ``upd_dict``:
321
322 0. If types of ``base_dict[upd_key]`` and ``upd_val`` do not match raise a
323 :py:obj:`TypeError`.
324
325 1. If ``base_dict[upd_key]`` is a dict: recursively deep-update it by ``upd_val``.
326
327 2. If ``base_dict[upd_key]`` not exist: set ``base_dict[upd_key]`` from a
328 (deep-) copy of ``upd_val``.
329
330 3. If ``upd_val`` is a list, extend list in ``base_dict[upd_key]`` by the
331 list in ``upd_val``.
332
333 4. If ``upd_val`` is a set, update set in ``base_dict[upd_key]`` by set in
334 ``upd_val``.
335 """
336
337 if not isinstance(base_dict, dict):
338 raise TypeError("argument 'base_dict' is not a dictionary type")
339 if not isinstance(upd_dict, dict):
340 raise TypeError("argument 'upd_dict' is not a dictionary type")
341
342 if names is None:
343 names = []
344
345 for upd_key, upd_val in upd_dict.items():
346
347
348 if isinstance(upd_val, dict):
349
350 if upd_key in base_dict:
351
352 if not isinstance(base_dict[upd_key], dict):
353 raise TypeError(f"type mismatch {'.'.join(names)}: is not a dict type in base_dict")
354 dict_deepupdate(
355 base_dict[upd_key],
356 upd_val,
357 names
358 + [
359 upd_key,
360 ],
361 )
362
363 else:
364
365 base_dict[upd_key] = copy.deepcopy(upd_val)
366
367 elif isinstance(upd_val, list):
368
369 if upd_key in base_dict:
370
371
372 if not isinstance(base_dict[upd_key], list):
373 raise TypeError(f"type mismatch {'.'.join(names)}: is not a list type in base_dict")
374 base_dict[upd_key].extend(upd_val)
375
376 else:
377
378
379 base_dict[upd_key] = copy.deepcopy(upd_val)
380
381 elif isinstance(upd_val, set):
382
383 if upd_key in base_dict:
384
385 if not isinstance(base_dict[upd_key], set):
386 raise TypeError(f"type mismatch {'.'.join(names)}: is not a set type in base_dict")
387 base_dict[upd_key].update(upd_val.copy())
388
389 else:
390
391
392 base_dict[upd_key] = upd_val.copy()
393
394 else:
395
396
397 base_dict[upd_key] = copy.copy(upd_val)