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