Skip to content

Commit 4b96c76

Browse files
committed
copilot feedback changes
1 parent 84b109c commit 4b96c76

2 files changed

Lines changed: 75 additions & 35 deletions

File tree

sds_data_manager/lambda_code/SDSCode/api_lambdas/release_api.py

Lines changed: 55 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,31 @@ def validate_query_params(event):
103103
}
104104

105105

106+
def parse_manifest_line(line: str):
107+
"""Parse a release manifest line into parts.
108+
109+
Parameters
110+
----------
111+
line : str
112+
A single non-empty manifest line.
113+
114+
Returns
115+
-------
116+
tuple[str, str, str, bool] | None
117+
Parsed ``(instrument, data_type, descriptor, release_flag)`` or
118+
``None`` if the line does not contain exactly four comma-separated
119+
fields.
120+
"""
121+
parts = [item.strip() for item in line.split(",")]
122+
if len(parts) != 4:
123+
raise ValueError(
124+
f"Manifest line must contain exactly four comma-separated fields: {line}"
125+
)
126+
127+
instrument, data_type, descriptor, release_flag = parts
128+
return instrument, data_type, descriptor, release_flag.lower() == "true"
129+
130+
106131
def latest_ancillary_release(
107132
session,
108133
start_date: datetime.datetime,
@@ -125,8 +150,6 @@ def latest_ancillary_release(
125150
----------
126151
session : orm session
127152
Database session.
128-
instrument : str
129-
Instrument name.
130153
start_date : datetime.datetime
131154
Start of query date range.
132155
end_date : datetime.datetime
@@ -136,12 +159,11 @@ def latest_ancillary_release(
136159
137160
Returns
138161
-------
139-
Query
140-
A query of a single file_path column, for use as an `.in_()`
141-
subquery so a large release stays a single UPDATE statement.
162+
list
163+
A list of the latest version ancillary files released.
142164
"""
143165
ancillary_table = models.AncillaryFiles
144-
instrument, data_type, descriptor, _ = (item.strip() for item in line.split(","))
166+
instrument, data_type, descriptor, _ = parse_manifest_line(line)
145167
# Scenarios:
146168
# hit, *, *, true, -- release all ancillary files
147169
# hit, ancillary, *, true -- release all ancillary descriptors
@@ -229,9 +251,26 @@ def latest_ancillary_release(
229251

230252

231253
def latest_science_release(session, start_date, end_date, line):
232-
"""Set the released flag to True for latest-version science files."""
254+
"""Set the released flag to True for latest-version science files.
255+
256+
Parameters
257+
----------
258+
session : orm session
259+
Database session.
260+
start_date : datetime.datetime
261+
Start of query date range.
262+
end_date : datetime.datetime
263+
End of query date range.
264+
line : str
265+
Manifest line describing the science release selection.
266+
267+
Returns
268+
-------
269+
list
270+
A list of the latest version science files released.
271+
"""
233272
sci = models.ScienceFiles.__table__.c
234-
instrument, data_type, descriptor, _ = (item.strip() for item in line.split(","))
273+
instrument, data_type, descriptor, _ = parse_manifest_line(line)
235274

236275
# Construct query logic based on different scenarios:
237276
# 1. hit, *, *, true -- release all data levels
@@ -319,7 +358,7 @@ def release_type_handler(query_params):
319358
with db.Session() as session:
320359
manifest_path = download_file(manifest_file)
321360

322-
manifest_file_obj = generate_imap_file_path(manifest_path.name)
361+
manifest_file_obj = generate_imap_file_path(manifest_file)
323362
start_date = datetime.datetime.strptime(manifest_file_obj.start_date, "%Y%m%d")
324363
end_date = datetime.datetime.strptime(manifest_file_obj.end_date, "%Y%m%d")
325364

@@ -334,8 +373,7 @@ def release_type_handler(query_params):
334373
if line.startswith("instrument,"):
335374
continue
336375

337-
_, data_type, _, release_flag = (item.strip() for item in line.split(","))
338-
release_flag = release_flag == "true"
376+
_, data_type, _, release_flag = parse_manifest_line(line)
339377
# If row is to exclude, skip release process.
340378
if not release_flag:
341379
continue
@@ -360,18 +398,20 @@ def release_type_handler(query_params):
360398

361399
return {
362400
"statusCode": 200,
363-
"body": json.dumps("Successfully released "),
401+
"body": json.dumps(
402+
f"Successfully released data per specification in {manifest_file}"
403+
),
364404
}
365405

366406

367407
def early_release_type_handler(query_params):
368408
"""Handle early-release requests using manifest file."""
369-
return {"statusCode": 200, "body": "Early release operation not supported yet."}
409+
return {"statusCode": 501, "body": "Early release operation not supported yet."}
370410

371411

372412
def unrelease_type_handler(query_params):
373413
"""Handle unrelease requests using manifest file."""
374-
return {"statusCode": 200, "body": "Unrelease operation not supported yet."}
414+
return {"statusCode": 501, "body": "Unrelease operation not supported yet."}
375415

376416

377417
def reprocess_type_handler(query_params):
@@ -380,7 +420,7 @@ def reprocess_type_handler(query_params):
380420
NOTE: This may not be needed. If not needed, remove support
381421
at imap-data-access before removing this.
382422
"""
383-
return {"statusCode": 200, "body": "Reprocess for data release not supported yet."}
423+
return {"statusCode": 501, "body": "Reprocess for data release not supported yet."}
384424

385425

386426
def lambda_handler(event, context):

tests/lambda_endpoints/test_release_api.py

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -136,15 +136,14 @@ def test_science_release(mock_download_file, session, tmp_path):
136136
assert result["statusCode"] == 200
137137

138138
rows = {r.file_path: r.released for r in session.query(models.ScienceFiles).all()}
139-
print(rows)
140139
assert rows["imap/hit/l0/imap_hit_l0_hk_20250110_v001.0000.pkts"] is False, (
141-
"Excluded in-range file should not be released"
142-
)
143-
assert rows["imap/hit/l0/imap_hit_l0_sci_20250120_v001.0000.pkts"] is True, (
144-
"Non-excluded in-range file should be released"
140+
"HK descriptor file should remain unreleased"
145141
)
146142
assert rows["imap/hit/l0/imap_hit_l0_hk_20250201_v001.0000.pkts"] is False, (
147-
"Out-of-range file must stay unreleased"
143+
"HK descriptor file should remain unreleased"
144+
)
145+
assert rows["imap/hit/l0/imap_hit_l0_sci_20250120_v001.0000.pkts"] is True, (
146+
"Sci descriptor file should be released"
148147
)
149148

150149

@@ -350,8 +349,7 @@ def test_ancillary_release_with_wildcard(mock_download_file, session, tmp_path):
350349
), "Out-of-range file must not be released"
351350

352351

353-
@patch("sds_data_manager.lambda_code.SDSCode.api_lambdas.release_api.download_file")
354-
def test_early_release(mock_download_file, session):
352+
def test_early_release():
355353
result = release_api.lambda_handler(
356354
event=_build_event(
357355
{
@@ -362,12 +360,11 @@ def test_early_release(mock_download_file, session):
362360
context={},
363361
)
364362

365-
assert result["statusCode"] == 200
363+
assert result["statusCode"] == 501
366364
assert result["body"] == "Early release operation not supported yet."
367365

368366

369-
@patch("sds_data_manager.lambda_code.SDSCode.api_lambdas.release_api.download_file")
370-
def test_unrelease_all_files_in_date_range(mock_download_file, session):
367+
def test_unrelease_all_files_in_date_range():
371368
result = release_api.lambda_handler(
372369
event=_build_event(
373370
{
@@ -378,7 +375,7 @@ def test_unrelease_all_files_in_date_range(mock_download_file, session):
378375
context={},
379376
)
380377

381-
assert result["statusCode"] == 200
378+
assert result["statusCode"] == 501
382379
assert result["body"] == "Unrelease operation not supported yet."
383380

384381

@@ -426,20 +423,21 @@ def test_latest_science_release(session):
426423

427424
# Query non-repoint files
428425
files = [
429-
("imap_swapi_l1_sci_20260407_v002.0002.cdf", "20260407", 2, 2),
430-
("imap_swapi_l1_sci_20260407_v001.0002.cdf", "20260407", 1, 2),
431-
("imap_swapi_l1_sci_20260407_v001.0001.cdf", "20260407", 1, 1),
432-
("imap_swapi_l1_sci_20260408_v001.0001.cdf", "20260408", 1, 1),
433-
("imap_swapi_l1_sci_20260408_v001.0002.cdf", "20260408", 1, 2),
434-
("imap_swapi_l1a_hk_20260408_v001.0001.cdf", "20260408", 1, 1),
426+
("imap_swapi_l1_sci_20260407_v002.0002.cdf", "sci", "20260407", 2, 2),
427+
("imap_swapi_l1_sci_20260407_v001.0002.cdf", "sci", "20260407", 1, 2),
428+
("imap_swapi_l1_sci_20260407_v001.0001.cdf", "sci", "20260407", 1, 1),
429+
("imap_swapi_l1_sci_20260408_v001.0001.cdf", "sci", "20260408", 1, 1),
430+
("imap_swapi_l1_sci_20260408_v001.0002.cdf", "sci", "20260408", 1, 2),
431+
# HK is used to see if it gets excluded properly in later step
432+
("imap_swapi_l1a_hk_20260408_v001.0001.cdf", "hk", "20260408", 1, 1),
435433
]
436-
for file_path, start_date, major_ver, minor_ver in files:
434+
for file_path, descriptor, start_date, major_ver, minor_ver in files:
437435
session.add(
438436
models.ScienceFiles(
439437
file_path=file_path,
440438
instrument="swapi",
441439
data_level="l1",
442-
descriptor="sci",
440+
descriptor=descriptor,
443441
start_date=datetime.datetime.strptime(start_date, "%Y%m%d"),
444442
repointing=None,
445443
major_version=major_ver,
@@ -462,6 +460,8 @@ def test_latest_science_release(session):
462460
"imap_swapi_l1_sci_20260407_v002.0002.cdf",
463461
], f"Expected only the latest non-repoint file, got: {file_paths}"
464462

463+
# In this release query, we only ask for latest sci files on April 8th,
464+
# so the HK file should be excluded and should not be returned.
465465
latest_non_repoint_files = release_api.latest_science_release(
466466
session,
467467
start_date=datetime.datetime.strptime("20260408", "%Y%m%d"),

0 commit comments

Comments
 (0)