Skip to content

Commit da87fdc

Browse files
RCAL-723 Fix model.meta.filename when saving model (#295)
Co-authored-by: Nadia Dencheva <nadia.dencheva@gmail.com>
1 parent 80cb53d commit da87fdc

File tree

3 files changed

+43
-18
lines changed

3 files changed

+43
-18
lines changed

CHANGES.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
- Allow assignment to or creation of node attributes using dot notation of object instances
55
with validation. [#284]
66

7+
- Bugfix for ``model.meta.filename`` not matching the filename of the file on disk. [#295]
8+
79
0.18.0 (2023-11-06)
810
===================
911

src/roman_datamodels/datamodels/_core.py

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,9 @@
1111
import copy
1212
import datetime
1313
import functools
14-
import os
15-
import os.path
1614
import sys
17-
from pathlib import PurePath
15+
from contextlib import contextmanager
16+
from pathlib import Path, PurePath
1817

1918
import asdf
2019
import numpy as np
@@ -48,6 +47,26 @@ def wrapper(self, *args, **kwargs):
4847
return wrapper
4948

5049

50+
@contextmanager
51+
def _temporary_update_filename(datamodel, filename):
52+
"""
53+
Context manager to temporarily update the filename of a datamodel so that it
54+
can be saved with that new file name without changing the current model's filename
55+
"""
56+
from roman_datamodels.stnode import Filename
57+
58+
if "meta" in datamodel._instance and "filename" in datamodel._instance.meta:
59+
old_filename = datamodel._instance.meta.filename
60+
datamodel._instance.meta.filename = Filename(filename)
61+
62+
yield
63+
datamodel._instance.meta.filename = old_filename
64+
return
65+
66+
yield
67+
return
68+
69+
5170
class DataModel(abc.ABC):
5271
"""Base class for all top level datamodels"""
5372

@@ -181,17 +200,9 @@ def clone(target, source, deepcopy=False, memo=None):
181200
target._ctx = target
182201

183202
def save(self, path, dir_path=None, *args, **kwargs):
184-
if callable(path):
185-
path_head, path_tail = os.path.split(path(self.meta.filename))
186-
else:
187-
path_head, path_tail = os.path.split(path)
188-
base, ext = os.path.splitext(path_tail)
189-
if isinstance(ext, bytes):
190-
ext = ext.decode(sys.getfilesystemencoding())
191-
192-
if dir_path:
193-
path_head = dir_path
194-
output_path = os.path.join(path_head, path_tail)
203+
path = Path(path(self.meta.filename) if callable(path) else path)
204+
output_path = Path(dir_path) / path.name if dir_path else path
205+
ext = path.suffix.decode(sys.getfilesystemencoding()) if isinstance(path.suffix, bytes) else path.suffix
195206

196207
# TODO: Support gzip-compressed fits
197208
if ext == ".asdf":
@@ -206,10 +217,10 @@ def open_asdf(self, init=None, **kwargs):
206217
return asdf.open(init, **kwargs) if isinstance(init, str) else asdf.AsdfFile(init, **kwargs)
207218

208219
def to_asdf(self, init, *args, **kwargs):
209-
with validate.nuke_validation():
210-
asdffile = self.open_asdf(**kwargs)
211-
asdffile.tree = {"roman": self._instance}
212-
asdffile.write_to(init, *args, **kwargs)
220+
with validate.nuke_validation(), _temporary_update_filename(self, Path(init).name):
221+
asdf_file = self.open_asdf(**kwargs)
222+
asdf_file.tree = {"roman": self._instance}
223+
asdf_file.write_to(init, *args, **kwargs)
213224

214225
def get_primary_array_name(self):
215226
"""

tests/test_models.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,3 +804,15 @@ def test_datamodel_construct_like_from_like(model):
804804
new_mdl = model(mdl)
805805
assert new_mdl is mdl
806806
assert new_mdl._iscopy == "foo" # Verify that the constructor didn't override stuff
807+
808+
809+
def test_datamodel_save_filename(tmp_path):
810+
filename = tmp_path / "fancy_filename.asdf"
811+
ramp = utils.mk_datamodel(datamodels.RampModel, shape=(2, 8, 8))
812+
assert ramp.meta.filename != filename.name
813+
814+
ramp.save(filename)
815+
assert ramp.meta.filename != filename.name
816+
817+
with datamodels.open(filename) as new_ramp:
818+
assert new_ramp.meta.filename == filename.name

0 commit comments

Comments
 (0)