Skip to content

Commit c347d5c

Browse files
authored
Merge pull request #744 from stvoutsin/issue-707
ENH: Declaratively define new-style standard IDs in Servicetype constraint
2 parents bfbc3e2 + f14fabb commit c347d5c

File tree

3 files changed

+38
-21
lines changed

3 files changed

+38
-21
lines changed

CHANGES.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ Enhancements and Fixes
66

77
- Support VOTableFile in accessible_table and broadcast_samp [#745]
88

9+
- Declaratively define new-style standard IDs in Servicetype constraint [#744]
10+
911
- Fix raise_if_error() to use cached job phase instead of re-polling [#743]
1012

1113
- Add ``pyvo.registry.get_RegTAP_service_url()`` to allow users to inspect the

pyvo/registry/rtcons.py

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@
3737
("image", "sia"),
3838
("sia", "sia"),
3939
("sia1", "sia"),
40-
# SIA2 is irregular
41-
# funky scheme used by SIA2 without breaking everything else
4240
("spectrum", "ssa"),
4341
("ssap", "ssa"),
4442
("ssa", "ssa"),
@@ -50,6 +48,14 @@
5048
("tap", "tap"),
5149
]}
5250

51+
# New-style standard IDs carry a #fragment with a minor version and cannot
52+
# be matched with equality, so we match them with LIKE patterns instead.
53+
NEW_STYLE_STDIDS = {
54+
"sia2": ("ivo://ivoa.net/std/sia#query-2.%", "ivo://ivoa.net/std/sia#query-aux-2.%"),
55+
"hats": ("ivo://ivoa.net/std/hats#hats-%", None),
56+
"hips": ("ivo://ivoa.net/std/hips#hips-1.%", None),
57+
}
58+
5359

5460
class RegTAPFeatureMissing(dalq.DALQueryError):
5561
"""
@@ -411,7 +417,7 @@ def __init__(self, *stds):
411417
match records that have any of them.
412418
"""
413419
self.stdids = set()
414-
self.extra_fragments = []
420+
self.like_patterns = set()
415421

416422
for std in stds:
417423
if std in ('image', 'spectrum'):
@@ -425,38 +431,34 @@ def __init__(self, *stds):
425431
self.stdids.add(SERVICE_TYPE_MAP[std])
426432
elif "://" in std:
427433
self.stdids.add(std)
428-
elif std == 'sia2':
429-
self.extra_fragments.append(
430-
"standard_id like 'ivo://ivoa.net/std/sia#query-2.%'")
431-
elif std == 'hats':
432-
self.extra_fragments.append(
433-
"standard_id like 'ivo://ivoa.net/std/hats#hats-%'")
434-
elif std == 'hips':
435-
self.extra_fragments.append(
436-
"standard_id like 'ivo://ivoa.net/std/hips#hipslist-%'")
434+
elif std in NEW_STYLE_STDIDS:
435+
self.like_patterns.add(NEW_STYLE_STDIDS[std][0])
437436
else:
438437
raise dalq.DALQueryError("Service type {} is neither a full"
439438
" standard URI nor one of the bespoke identifiers"
440-
" {}, sia2, hats, hips".format(std, ", ".join(SERVICE_TYPE_MAP)))
439+
" {}, {}".format(std, ", ".join(SERVICE_TYPE_MAP),
440+
", ".join(NEW_STYLE_STDIDS)))
441441

442442
def clone(self):
443443
"""returns a copy of this servicetype constraint.
444444
"""
445445
new_constraint = Servicetype()
446446
new_constraint.stdids = set(self.stdids)
447-
new_constraint.extra_fragments = self.extra_fragments[:]
447+
new_constraint.like_patterns = set(self.like_patterns)
448448
return new_constraint
449449

450450
def get_search_condition(self, service):
451-
# we sort the stdids to make it easy for tests (and it's
451+
# we sort to make it easy for tests (and it's
452452
# virtually free for the small sets we have here).
453453
fragments = []
454454
std_ids = ", ".join(make_sql_literal(s)
455455
for s in sorted(self.stdids))
456456
if std_ids:
457457
fragments.append(f"standard_id IN ({std_ids})")
458+
for pattern in sorted(self.like_patterns):
459+
fragments.append(f"standard_id like '{pattern}'")
458460

459-
return " OR ".join(fragments + self.extra_fragments)
461+
return " OR ".join(fragments)
460462

461463
def include_auxiliary_services(self):
462464
"""returns a Servicetype constraint that has self's
@@ -465,11 +467,10 @@ def include_auxiliary_services(self):
465467
This is a convenience to maintain registry.search's signature.
466468
"""
467469
expanded = self.clone()
468-
expanded.stdids |= {
469-
std + '#aux' for std in expanded.stdids}
470-
if "standard_id like 'ivo://ivoa.net/std/sia#query-2.%'" in expanded.extra_fragments:
471-
expanded.extra_fragments.append(
472-
"standard_id like 'ivo://ivoa.net/std/sia#query-aux-2.%'")
470+
expanded.stdids |= {std + '#aux' for std in expanded.stdids}
471+
for main_pattern, aux_pattern in NEW_STYLE_STDIDS.values():
472+
if main_pattern in expanded.like_patterns and aux_pattern:
473+
expanded.like_patterns.add(aux_pattern)
473474
return expanded
474475

475476

pyvo/registry/tests/test_rtcons.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,20 @@ def test_sia2_aux(self):
185185
" OR standard_id like 'ivo://ivoa.net/std/sia#query-2.%'"
186186
" OR standard_id like 'ivo://ivoa.net/std/sia#query-aux-2.%'"))
187187

188+
def test_hats(self):
189+
assert (rtcons.Servicetype("hats").get_search_condition(FAKE_GAVO)
190+
== "standard_id like 'ivo://ivoa.net/std/hats#hats-%'")
191+
192+
def test_hats_aux(self):
193+
# hats has no auxiliary service concept; aux expansion should not add a pattern
194+
constraint = rtcons.Servicetype("hats").include_auxiliary_services()
195+
assert (constraint.get_search_condition(FAKE_GAVO)
196+
== "standard_id like 'ivo://ivoa.net/std/hats#hats-%'")
197+
198+
def test_hips(self):
199+
assert (rtcons.Servicetype("hips").get_search_condition(FAKE_GAVO)
200+
== "standard_id like 'ivo://ivoa.net/std/hips#hips-1.%'")
201+
188202
def test_image_deprecated(self):
189203
with pytest.warns(AstropyDeprecationWarning):
190204
assert (rtcons.Servicetype("image").get_search_condition(FAKE_GAVO)

0 commit comments

Comments
 (0)