diff --git a/pyvo/dal/tap.py b/pyvo/dal/tap.py index e5511e84e..5ee5ef74a 100644 --- a/pyvo/dal/tap.py +++ b/pyvo/dal/tap.py @@ -149,6 +149,38 @@ def tables(self): vosi.parse_tables(response.raw.read), tables_url) return self._tables + def _parse_examples(self, examples_uri, /, depth=0): + """returns the TAP queries from a DALI examples URI. + """ + if depth>5: + raise Exception("Suspecting endless recursion when" + " parsing TAP examples") + + response = self._session.get(examples_uri, stream=True) + if response.status_code == 404: + return [] + + try: + response.raise_for_status() + except requests.RequestException as ex: + raise DALServiceError.from_except(ex, examples_url) + + try: + root = xml.etree.ElementTree.parse( + io.BytesIO(response.content)).getroot() + exampleElements = root.findall('.//*[@property="query"]') + except Exception as ex: + raise DALServiceError.from_except(ex, examples_url) + + examples = [TAPQuery(self.baseurl, example.text) + for example in exampleElements] + + for continuation in root.findall('.//*[@property="continuation"]'): + examples.extend( + self._parse_examples(continuation.get("href"), depth+1)) + + return examples + @property def examples(self): """ @@ -157,23 +189,7 @@ def examples(self): if self._examples is None: examples_url = '{}/examples'.format(self.baseurl) - response = self._session.get(examples_url, stream=True) - if response.status_code == 404: - return [] - - try: - response.raise_for_status() - except requests.RequestException as ex: - raise DALServiceError.from_except(ex, examples_url) - - try: - root = xml.etree.ElementTree.parse(io.BytesIO(response.content)).getroot() - exampleElements = root.findall('.//*[@property="query"]') - except Exception as ex: - raise DALServiceError.from_except(ex, examples_url) - - self._examples = [TAPQuery(self.baseurl, example.text) for example in exampleElements] - + self._examples = self._parse_examples(examples_url) return self._examples @property diff --git a/pyvo/dal/tests/data/tap/examples.htm b/pyvo/dal/tests/data/tap/examples.htm index c4f85972a..8030eb166 100644 --- a/pyvo/dal/tests/data/tap/examples.htm +++ b/pyvo/dal/tests/data/tap/examples.htm @@ -1 +1,3 @@ -
The Table Access Protocol Service at HEASARC allow for simple geometric queries. For example, this query searches for observations in the rostmaster catalog within a circle of radius 1 degree of the coordinates (ra,dec)=(50,-85) -- i.e., basically a cone search -- and an exposure longer than 10000 seconds:
SELECT * FROM rosmaster WHERE exposure > 10000 and 1=CONTAINS(POINT('ICRS', ra, dec),CIRCLE('ICRS', 50, -85, 1))
The Table Access Protocol Service at HEASARC allow for simple geometric and cross-match queries. For example, this query searches for observations common to the rostmaster catalog AND the chanmaster catalog with a minimum exposure of 10ks.
SELECT * FROM rosmaster as ros INNER JOIN chanmaster as chan ON ros.name = chan.name WHERE ros.exposure > 10000 and chan.exposure > 10000 ORDER by ros.exposure
The Table Access Protocol Service at HEASARC allow for simple geometric queries. For example, this (slow) query searches for observations in the rostmaster catalog where a circle of radius 1 degree of the coordinates (ra,dec)=(50,-85) intersects with a circle of 1 degree radius around the center of the pointing:
SELECT * FROM rosmaster WHERE 1=INTERSECTS(CIRCLE('ICRS', ra, dec,1),CIRCLE('ICRS', 50, -85, 1))
The Table Access Protocol Service at HEASARC allow for simple geometric queries. For example, this query searches for observations in the rostmaster catalog where a pointing lies with a user-defined polygon, in this case a triangle with vertices (-5,-5), (5,-5), and (0,5)):
SELECT * FROM rosmaster WHERE exposure > 10000 AND 1=CONTAINS(POINT('ICRS', ra, dec),POLYGON('ICRS', -5, -5, 5, -5, 0, 5))
The Table Access Protocol Service at HEASARC allow for simple geometric queries. For example, this query computes the distance between rostmaster observations and a given point, selecting those observations near it, and ordering the result by that distance:
SELECT DISTANCE( POINT('ICRS', ra, dec), POINT('ICRS', 266.41683, -29.00781)) AS dist, * FROM rosmaster WHERE 1=CONTAINS( POINT('ICRS', ra, dec), CIRCLE('ICRS', 266.41683, -29.00781, 1)) ORDER BY dist ASC
The Table Access Protocol Service at HEASARC allow for simple geometric queries. For example, this query searches for observations in the rostmaster catalog within a circle of radius 1 degree of the coordinates (ra,dec)=(50,-85) -- i.e., basically a cone search -- and an exposure longer than 10000 seconds:
SELECT * FROM rosmaster WHERE exposure > 10000 and 1=CONTAINS(POINT('ICRS', ra, dec),CIRCLE('ICRS', 50, -85, 1))
The Table Access Protocol Service at HEASARC allow for simple geometric and cross-match queries. For example, this query searches for observations common to the rostmaster catalog AND the chanmaster catalog with a minimum exposure of 10ks.
SELECT * FROM rosmaster as ros INNER JOIN chanmaster as chan ON ros.name = chan.name WHERE ros.exposure > 10000 and chan.exposure > 10000 ORDER by ros.exposure
The Table Access Protocol Service at HEASARC allow for simple geometric queries. For example, this (slow) query searches for observations in the rostmaster catalog where a circle of radius 1 degree of the coordinates (ra,dec)=(50,-85) intersects with a circle of 1 degree radius around the center of the pointing:
SELECT * FROM rosmaster WHERE 1=INTERSECTS(CIRCLE('ICRS', ra, dec,1),CIRCLE('ICRS', 50, -85, 1))
The Table Access Protocol Service at HEASARC allow for simple geometric queries. For example, this query searches for observations in the rostmaster catalog where a pointing lies with a user-defined polygon, in this case a triangle with vertices (-5,-5), (5,-5), and (0,5)):
SELECT * FROM rosmaster WHERE exposure > 10000 AND 1=CONTAINS(POINT('ICRS', ra, dec),POLYGON('ICRS', -5, -5, 5, -5, 0, 5))
The Table Access Protocol Service at HEASARC allow for simple geometric queries. For example, this query computes the distance between rostmaster observations and a given point, selecting those observations near it, and ordering the result by that distance:
SELECT DISTANCE( POINT('ICRS', ra, dec), POINT('ICRS', 266.41683, -29.00781)) AS dist, * FROM rosmaster WHERE 1=CONTAINS( POINT('ICRS', ra, dec), CIRCLE('ICRS', 266.41683, -29.00781, 1)) ORDER BY dist ASC
These are examples for ADQL you can run in TAP services carrying
+ an ivoa.obscore
table. See
+ ObsCore for the underlying
+ data model.
Suppose you read in an old amateur observer's log there was an unexpected +object on the night sky in the cold winter nights of the week between January +12th and 18th, 1903 – and now you would like to see whether there could +be an observation of such a thing.
++SELECT s_ra, s_dec, t_min FROM ivoa.obscore + WHERE t_min BETWEEN gavo_to_mjd('1903-01-12') + AND gavo_to_mjd('1903-01-19') ++
There is also a shortcut via user defined functions. As an extension +to regular ADQL, DaCHS lets you write gavo_simbadpoint('object') and replaces +the result with a position obtained from simbad, like this:
++SELECT access_url, t_exptime, t_min FROM ivoa.obscore + WHERE + t_min BETWEEN gavo_to_mjd('J2416128.5') + AND gavo_to_mjd('J2416133.5') AND + 1=CONTAINS(gavo_simbadpoint('Aldebaran'), + CIRCLE('ICRS', s_ra, s_dec, 15)) ++