Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions source_modelling/gsf.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,15 @@ def write_gsf(gsf_df: pd.DataFrame, gsf_filepath: Path):
The path to the GSF file to write.
"""

if "loc_rake" not in gsf_df:
raise ValueError("The DataFrame must have a 'loc_rake' column.")
# Defaults are filled on a copy: write_gsf serialises the frame it is
# given and must not modify the caller's DataFrame.
gsf_df = gsf_df.copy(deep=False)
if "init_time" not in gsf_df:
gsf_df["init_time"] = -1
if "slip" not in gsf_df:
gsf_df["slip"] = -1
if "loc_rake" not in gsf_df:
raise ValueError("The DataFrame must have a 'loc_rake' column.")
with open(gsf_filepath, "w") as gsf_file:
gsf_file.write(f"{len(gsf_df)}\n")
gsf_df.to_csv(
Expand Down
36 changes: 36 additions & 0 deletions tests/test_gsf.py
Original file line number Diff line number Diff line change
Expand Up @@ -359,3 +359,39 @@ def test_read_gsf(tmp_path: Path):
]
),
)


def test_write_gsf_does_not_mutate_input(tmp_path: Path):
"""write_gsf must serialise its input without modifying it.

Regression test: the ``init_time`` and ``slip`` defaults were assigned
directly into the caller's DataFrame, so a frame handed to ``write_gsf``
came back carrying two columns of ``-1`` sentinels. The assignments also
sat above the ``loc_rake`` validation, so the mutation happened even when
``write_gsf`` went on to raise and write nothing.
"""
gsf_df = pd.DataFrame(
{
"lon": [172.6],
"lat": [-43.5],
"dep": [1.0],
"sub_dx": [1.0],
"sub_dy": [1.0],
"loc_stk": [0.0],
"loc_dip": [0.0],
"loc_rake": [0.0],
"seg_no": [0],
}
)
expected_columns = list(gsf_df.columns)

gsf.write_gsf(gsf_df, tmp_path / "out.gsf")

assert list(gsf_df.columns) == expected_columns

# the failure path must not mutate either
missing_rake = gsf_df.drop(columns=["loc_rake"])
expected_columns = list(missing_rake.columns)
with pytest.raises(ValueError, match="loc_rake"):
gsf.write_gsf(missing_rake, tmp_path / "out2.gsf")
assert list(missing_rake.columns) == expected_columns
Loading