Skip to content

Commit

Permalink
Merge pull request #428 from msdemlei/registry-and-sia2
Browse files Browse the repository at this point in the history
Making SIA2 discoverable as intended by the standard.
  • Loading branch information
bsipocz authored Apr 12, 2023
2 parents af6c204 + 90418d5 commit eb24f44
Show file tree
Hide file tree
Showing 7 changed files with 166 additions and 81 deletions.
2 changes: 1 addition & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
``SIA2_PARAMETERS_DESC``. The old names now issue an
``AstropyDeprecationWarning``. [#419]

- Registry search now finds SIA v2 services. [#422]
- Registry search now finds SIA v2 services. [#422, #428]


1.4.1 (2023-03-07)
Expand Down
5 changes: 5 additions & 0 deletions pyvo/dal/sia2.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,11 @@ def _tolist(value):
class SIA2Service(DALService, AvailabilityMixin, CapabilityMixin):
"""
a representation of an SIA2 service
Note that within pyVO, SIA2 services are associated with the
(non-existing) standard id ivo://ivoa.net/std/sia2 rather than
ivo://ivoa.net/std/sia#query-2.0 as in the standard; users should
generally not notice that, though.
"""

def __init__(self, baseurl, session=None):
Expand Down
31 changes: 28 additions & 3 deletions pyvo/registry/regtap.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,29 @@ def expand_stdid(s):
return "ivo://ivoa.net/std/" + s


def regularize_SIA2_id(standard_id):
"""returns standard_id with SIA2 standard ids modified to what they should
have been.
Regrettably, SIA2 uses the same standardID as SIA1; sure, they use
different fragments, but that doesn't really help with the logic
we have here.
To make up for that, we replace them with the sia2 ids they should
have had on input. This function assumes lowercased ids as they
come from RegTAP services.
"""
if standard_id.startswith("ivo://ivoa.net/std/sia#query-2"):
return "ivo://ivoa.net/std/sia2"
elif standard_id.startswith("ivo://ivoa.net/std/sia#query-aux-2"):
# query-aux-2 is mentioned in discovering data collections,
# which isn't really the place to define this. But then
# it's endorsed, and SIA2 doesn't say anything about it.
return "ivo://ivoa.net/std/sia2#aux"
else:
return standard_id


@functools.lru_cache(1)
def get_RegTAP_service():
"""
Expand Down Expand Up @@ -284,7 +307,7 @@ class Interface:
service_for_standardid = {
"ivo://ivoa.net/std/conesearch": scs.SCSService,
"ivo://ivoa.net/std/sia": sia.SIAService,
"ivo://ivoa.net/std/sia#query-2.0": sia2.SIA2Service,
"ivo://ivoa.net/std/sia2": sia2.SIA2Service,
"ivo://ivoa.net/std/ssa": ssa.SSAService,
"ivo://ivoa.net/std/sla": sla.SLAService,
"ivo://ivoa.net/std/tap": tap.TAPService}
Expand Down Expand Up @@ -336,6 +359,7 @@ def supports(self, standard_id):
"""
if not self.standard_id:
return False
standard_id = regularize_SIA2_id(standard_id)
return self.standard_id.split("#")[0] == standard_id.split("#")[0]


Expand Down Expand Up @@ -388,8 +412,9 @@ def __init__(self, results, index, session=None):

self._mapping["access_urls"
] = self._parse_pseudo_array(self._mapping["access_urls"])
self._mapping["standard_ids"
] = self._parse_pseudo_array(self._mapping["standard_ids"])
self._mapping["standard_ids"] = [
regularize_SIA2_id(id) for id in
self._parse_pseudo_array(self._mapping["standard_ids"])]
self._mapping["intf_types"
] = self._parse_pseudo_array(self._mapping["intf_types"])
self._mapping["intf_roles"
Expand Down
46 changes: 35 additions & 11 deletions pyvo/registry/rtcons.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
for k, v in [
("image", "sia"),
("sia", "sia"),
("sia2", "sia#query-2.0"),
# SIA2 is irregular
# funky scheme used by SIA2 without breaking everything else
("spectrum", "ssa"),
("ssap", "ssa"),
("ssa", "ssa"),
Expand Down Expand Up @@ -268,10 +269,10 @@ class Servicetype(Constraint):
You can also pass in the standards' ivoid (which
generally looks like
``ivo://ivoa.net/std/<standardname>`` and have to be URIs with
a scheme part in any case); note, however, that for standards
pyVO does not know about it will not build service instances for
you.
``ivo://ivoa.net/std/<standardname>`` (except for SIA2) and have
to be URIs with a scheme part in any case); note, however, that for
standards pyVO does not know about it will not build service instances
for you.
Multiple service types can be passed in; a match in that case
is for records having any of the service types passed in.
Expand All @@ -297,31 +298,53 @@ def __init__(self, *stds):
match records that have any of them.
"""
self.stdids = set()
self.extra_fragments = []

for std in stds:
if std in SERVICE_TYPE_MAP:
self.stdids.add(SERVICE_TYPE_MAP[std])
elif "://" in std:
self.stdids.add(std)
elif std == 'sia2':
self.extra_fragments.append(
"standard_id like 'ivo://ivoa.net/std/sia#query-2.%'")
else:
raise dalq.DALQueryError("Service type {} is neither a full"
" standard URI nor one of the bespoke identifiers"
" {}".format(std, ", ".join(SERVICE_TYPE_MAP)))
" {}, sia2".format(std, ", ".join(SERVICE_TYPE_MAP)))

def clone(self):
"""returns a copy of this servicetype constraint.
"""
new_constraint = Servicetype()
new_constraint.stdids = set(self.stdids)
new_constraint.extra_fragments = self.extra_fragments[:]
return new_constraint

def get_search_condition(self):
# we sort the stdids to make it easy for tests (and it's
# virtually free for the small sets we have here).
return "standard_id IN ({})".format(
", ".join(make_sql_literal(s) for s in sorted(self.stdids)))
fragments = []
std_ids = ", ".join(make_sql_literal(s)
for s in sorted(self.stdids))
if std_ids:
fragments.append(f"standard_id IN ({std_ids})")

return " OR ".join(fragments + self.extra_fragments)

def include_auxiliary_services(self):
"""returns a Servicetype constraint that has self's
service types but includes the associated auxiliary services.
This is a convenience to maintain registry.search's signature.
"""
return Servicetype(*(self.stdids | set(
std + '#aux' for std in self.stdids)))
expanded = self.clone()
expanded.stdids |= set(
std + '#aux' for std in expanded.stdids)
if "standard_id like 'ivo://ivoa.net/std/sia#query-2.%'" in expanded.extra_fragments:
expanded.extra_fragments.append(
"standard_id like 'ivo://ivoa.net/std/sia#query-aux-2.%'")
return expanded


class Waveband(Constraint):
Expand Down Expand Up @@ -735,7 +758,8 @@ def _to_mjd(self, quant):


# NOTE: If you add new Contraint-s, don't forget to add them in
# registry.__init__ and in docs/registry/index.rst.
# registry.__init__, in docs/registry/index.rst and in the docstring
# of regtap.query.


def build_regtap_query(constraints):
Expand Down
Loading

0 comments on commit eb24f44

Please sign in to comment.