Skip to content

Commit 9d72bac

Browse files
author
Tomas Babej
committed
Mapper: Support renaming the file during save() if required
1 parent 5d72550 commit 9d72bac

File tree

1 file changed

+23
-2
lines changed

1 file changed

+23
-2
lines changed

datafiles/mapper.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from . import config, formats, hooks
1616
from .converters import Converter, List, map_type, resolve
1717
from .types import Missing, Trilean
18-
from .utils import display, get_default_field_value, recursive_update, write
18+
from .utils import display, get_default_field_value, recursive_update, write, remove
1919

2020

2121
class Mapper:
@@ -45,6 +45,7 @@ def __init__(
4545
self._last_load = 0.0
4646
self._last_data: Dict = {}
4747
self._root = root
48+
self._original_path = None
4849

4950
@property
5051
def classname(self) -> str:
@@ -58,7 +59,13 @@ def path(self) -> Optional[Path]:
5859
path = Path(self._pattern.format(self=self._instance)).expanduser()
5960
if path.is_absolute() or self._pattern.startswith("./"):
6061
log.debug(f"Detected static pattern: {path}")
61-
return path.resolve()
62+
63+
resolved_path = path.resolve()
64+
65+
if self._original_path is None:
66+
self._original_path = resolved_path
67+
68+
return resolved_path
6269

6370
cls = self._instance.__class__
6471
try:
@@ -69,6 +76,8 @@ def path(self) -> Optional[Path]:
6976
root = Path.cwd()
7077

7178
path = (root / path).resolve()
79+
if self._original_path is None:
80+
self._original_path = path
7281
log.debug(f"Detected dynamic pattern: {path}")
7382
return path
7483

@@ -264,6 +273,15 @@ def save(self, *, include_default_values: Trilean = None, _log=True) -> None:
264273
self._root.save(include_default_values=include_default_values, _log=_log)
265274
return
266275

276+
# Determine whether the attributes that are involved in the path were changed
277+
file_rename_required = False
278+
with hooks.disabled(): # hooks have to be disabled to prevent infinite loop
279+
if "path" in self.__dict__:
280+
del self.__dict__["path"] # invalidate the cached property
281+
282+
if self._original_path is not None and self.path != self._original_path:
283+
file_rename_required = True
284+
267285
if self.path:
268286
if self.exists and self._frozen:
269287
raise dataclasses.FrozenInstanceError(
@@ -279,6 +297,9 @@ def save(self, *, include_default_values: Trilean = None, _log=True) -> None:
279297
text = self._get_text(include_default_values=include_default_values)
280298

281299
write(self.path, text, display=True)
300+
if file_rename_required:
301+
remove(self._original_path)
302+
self._original_path = self.path
282303

283304
self.modified = False
284305

0 commit comments

Comments
 (0)