47 lines
1.0 KiB
Python
47 lines
1.0 KiB
Python
import shutil
|
|
|
|
from copy import deepcopy
|
|
from pathlib import Path
|
|
|
|
|
|
def deep_update(original, updates):
|
|
"""
|
|
Recursively update `original` with values from `updates`.
|
|
|
|
- Dicts are merged recursively.
|
|
- Scalars replace existing values.
|
|
- Lists are replaced entirely.
|
|
"""
|
|
if not isinstance(original, dict) or not isinstance(updates, dict):
|
|
return deepcopy(updates)
|
|
|
|
result = deepcopy(original)
|
|
|
|
for key, value in updates.items():
|
|
if (
|
|
key in result
|
|
and isinstance(result[key], dict)
|
|
and isinstance(value, dict)
|
|
):
|
|
result[key] = deep_update(result[key], value)
|
|
else:
|
|
result[key] = deepcopy(value)
|
|
|
|
return result
|
|
|
|
|
|
|
|
def copytree_no_copystat(src, dst):
|
|
src = Path(src)
|
|
dst = Path(dst)
|
|
|
|
dst.mkdir(parents=True, exist_ok=True)
|
|
|
|
for item in src.iterdir():
|
|
target = dst / item.name
|
|
|
|
if item.is_dir():
|
|
copytree_no_copystat(item, target)
|
|
else:
|
|
shutil.copy2(item, target)
|