Skip to content

Commit 2c991b2

Browse files
authored
allow uris for member expnames (#305)
2 parents 1e989bb + 9f61a81 commit 2c991b2

3 files changed

Lines changed: 60 additions & 3 deletions

File tree

changes/305.feature.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Support URIs in member expnames in ModelLibrary.

src/stpipe/library.py

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from collections.abc import Iterable, MutableMapping
88
from pathlib import Path
99
from types import MappingProxyType
10+
from urllib.parse import urlparse
1011

1112
import asdf
1213

@@ -279,8 +280,9 @@ def __init__(
279280

280281
for index, member in enumerate(self._members):
281282
if "group_id" not in member:
282-
filename = os.path.join(self._asn_dir, member["expname"])
283-
member["group_id"] = self._to_group_id(filename, index)
283+
member["group_id"] = self._to_group_id(
284+
self._member_to_filename(member), index
285+
)
284286

285287
if not on_disk:
286288
# if models were provided as input, assign the members here
@@ -548,6 +550,27 @@ def _assign_member_to_model(self, model, member):
548550
if "asn_pool" in self.asn:
549551
model.meta.asn["pool_name"] = self.asn["asn_pool"]
550552

553+
def _member_to_filename(self, member):
554+
"""
555+
Resolve a filename for the provided member.
556+
557+
Parameters
558+
----------
559+
member : dict
560+
Member definition (likely from an association).
561+
562+
Returns
563+
-------
564+
filename : str
565+
Filename for the provided member.
566+
"""
567+
member_filename = member["expname"]
568+
if self._asn_dir is None:
569+
return member_filename
570+
if urlparse(member_filename).scheme:
571+
return member_filename
572+
return os.path.join(self._asn_dir, member["expname"])
573+
551574
def _load_member(self, index):
552575
"""
553576
Load a model for the association member at the provided index.
@@ -565,7 +588,7 @@ def _load_member(self, index):
565588
model : DataModel
566589
"""
567590
member = self._members[index]
568-
filename = os.path.join(self._asn_dir, member["expname"])
591+
filename = self._member_to_filename(member)
569592

570593
model = self._datamodels_open(filename, **self._datamodels_open_kwargs)
571594

tests/test_library.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
_N_GROUPS = len(set(_GROUP_IDS))
2424
_PRODUCT_NAME = "foo_out"
2525
_INIT_TYPES = ("filename", "asn", "models")
26+
_TEST_URI_SCHEME = "file://"
2627

2728

2829
def _load_asn(filename):
@@ -84,6 +85,14 @@ def _model_to_group_id(self, model):
8485
raise NoGroupID(f"{model} missing group_id")
8586

8687

88+
class URIModelLibrary(ModelLibrary):
89+
def _datamodels_open(self, filename, **kwargs):
90+
return super()._datamodels_open(filename.removeprefix(_TEST_URI_SCHEME))
91+
92+
def _filename_to_group_id(self, filename):
93+
return super()._filename_to_group_id(filename.removeprefix(_TEST_URI_SCHEME))
94+
95+
8796
def _library_to_models(library):
8897
"""
8998
A few tests are easier to understand and write when
@@ -145,6 +154,17 @@ def example_asn_path(example_models, tmp_path):
145154
return asn_filename
146155

147156

157+
@pytest.fixture
158+
def example_uri_asn_path(example_asn_path):
159+
asn_dir = example_asn_path.parent
160+
asn_data = _load_asn(example_asn_path)
161+
for member in asn_data["products"][0]["members"]:
162+
member["expname"] = _TEST_URI_SCHEME + str(asn_dir / member["expname"])
163+
asn_filename = asn_dir / "uri_asn.json"
164+
_write_asn(asn_data, asn_filename)
165+
return asn_filename
166+
167+
148168
@pytest.fixture
149169
def example_library(example_asn_path):
150170
"""
@@ -801,3 +821,16 @@ def test_get_filename(table_name, filename):
801821
if table_name != "MISSING":
802822
lib._asn["table_name"] = table_name
803823
assert Step._get_filename(lib) == filename
824+
825+
826+
@pytest.mark.parametrize("loaded", [False, True])
827+
def test_uri_member_paths(example_uri_asn_path, loaded):
828+
if loaded:
829+
asn = _load_asn(example_uri_asn_path)
830+
else:
831+
asn = example_uri_asn_path
832+
lib = URIModelLibrary(asn)
833+
with lib:
834+
for i, model in enumerate(lib):
835+
assert model
836+
lib.shelve(model, i, modify=False)

0 commit comments

Comments
 (0)