Source code for lcc.db_tier.TAP_query
from astropy.coordinates.sky_coordinate import SkyCoord
from gavo import votable
from gavo.votable.tapquery import RemoteError, WrongStatus, NetworkError
from .base_query import LightCurvesDb
from lcc.entities.exceptions import QueryInputError, NoInternetConnection
[docs]class TapClient(LightCurvesDb):
'''
Common class for all TAP db clients
Attributes
----------
COO_UNIT_CONV : int, float
Conversion rate of coordinates from degrees
QUOTING : list, tuple
Expressions with any of these symbols are quoted
'''
COO_UNIT_CONV = 1
QUOTING = [" ", "/", "_", "-", ".", "+"]
SPECIAL_SYMB = ["<", ">", "="]
REPEAT_CON = 10
COUNTER_CON = 0
[docs] def postQuery(self, tap_params):
'''
Post query according to given parameters
Parameters
-----------
tap_params : dict
Tap query parameters. It has to contains four keys.
Dict keys:
URL(str)
Url of tap server
table(str)
Name of table for query
select(str/list)
Select string or list of column names
conditions(list/tuple)
For each condition in the list of conditions there
is a tuple - ("name of column", "condition") or
("name of column", "lower value", "upper value" for
search in the range
Returns
--------
list of lists
Result from the query as nested lists
'''
# Load tap protocol parameters
self.URL = tap_params["URL"]
self.table = tap_params["table"]
if "/" in self.table and not (self.table.startswith('"') or
self.table.startswith("'")):
self.table = '"' + self.table + '"'
self.conditions = tap_params["conditions"]
self.select = tap_params["select"]
query = self._get_select_text() + self._get_from_text() + \
self._get_where_text()
# Run query
try:
job = votable.ADQLTAPJob(self.URL, query, timeout=1)
job.run()
except RemoteError:
raise QueryInputError(
"Wrong TAP query name column/table\n%s" % query)
except WrongStatus:
raise QueryInputError("Wrong TAP query url")
except NetworkError:
if self.COUNTER_CON < self.REPEAT_CON:
self.postQuery(tap_params)
else:
raise NoInternetConnection()
retrieve_data = votable.load(job.openResult())[0]
job.delete()
return retrieve_data
def _get_select_text(self):
'''Get SELECT part for query'''
if (isinstance(self.select, (list, tuple, set))):
select_text = "SELECT "
for sel in set(self.select):
if sel:
select_text += '"%s", ' % sel
select_text = select_text[:-2] + " "
elif (isinstance(self.select, str)):
select_text = "SELECT %s " % self.select
else:
raise QueryInputError(
"Select option was not resolved for TAP query\n%s" % self.select)
return select_text
def _get_from_text(self):
'''Get GET part for query'''
if (type(self.table) == str):
return "FROM " + self.table + " "
raise QueryInputError("Given table name is not string")
def _get_where_text(self):
'''Get WHERE part for query'''
where_text = "WHERE "
for _condition in self.conditions:
condition = self._transfromCoo(_condition)
condition = [self._quoteIfNeeded(cond) for cond in condition]
if type(condition[1]) is tuple:
condition = (condition[0], condition[1][0], condition[1][1])
if (len(condition) == 3):
where_text += "({0} BETWEEN {1} AND {2}) AND ".format(*
condition)
elif (len(condition) == 2):
if condition[1].strip().startswith("'") or condition[1].strip().startswith('"'):
cleaned_cond = condition[1].strip()[1:-1]
else:
cleaned_cond = condition[1].strip()
if cleaned_cond[0] in self.SPECIAL_SYMB:
where_text += "({0} {1}) AND ".format(
condition[0], cleaned_cond)
else:
where_text += "({0} = {1}) AND ".format(*condition)
else:
raise QueryInputError(
"Unresolved TAP query condition: %s" % condition)
where_text = where_text[:-4]
print "whh", where_text
return where_text
def _transfromCoo(self, condition):
if isinstance(condition[1], SkyCoord):
new_cond = [condition[0]]
for i in range(1, len(condition)):
new_cond.append(condition[i].degree * self.COO_UNIT_CONV)
return new_cond
return condition
def _areaSearch(self, ra, dec, delta):
ra1, ra2, dec1, dec2 = self._getRanges(ra, dec, delta)
return (ra1, ra2), (dec1, dec2)
def _quoteIfNeeded(self, value):
value = str(value).strip()
need_quoting = True in [let in value for let in self.QUOTING]
if (need_quoting and not value.startswith("'") and
not value.startswith('"')):
return "'%s'" % value
return value