diff --git a/astroquery/astorbdb/__init__.py b/astroquery/astorbdb/__init__.py new file mode 100644 index 0000000000..e5a2b0ee69 --- /dev/null +++ b/astroquery/astorbdb/__init__.py @@ -0,0 +1,39 @@ +# Licensed under a 3-clause BSD style license - see LICENSE.rst + +""" +ASTORBDB +------------------------- + +:author: Henry Hsieh (hhsieh@gmail.com) +""" + +# Make the URL of the server, timeout and other items configurable +# See +# for docs and examples on how to do this +# Below is a common use case + +from astropy import config as _config + + +class Conf(_config.ConfigNamespace): + """ + Configuration parameters for `astroquery.astorbdb`. + """ + server = _config.ConfigItem( + ['https://asteroid.lowell.edu/api/asteroids/'], + 'AstorbDB') + + timeout = _config.ConfigItem( + 30, + 'Time limit for connecting to template_module server.') + + +conf = Conf() + +# Now import your public class +# Should probably have the same name as your module +from .core import AstInfo, AstInfoClass + +__all__ = ['AstInfo', 'AstInfoClass', + 'Conf', 'conf', + ] diff --git a/astroquery/astorbdb/core.py b/astroquery/astorbdb/core.py new file mode 100644 index 0000000000..4a40735870 --- /dev/null +++ b/astroquery/astorbdb/core.py @@ -0,0 +1,720 @@ +# Licensed under a 3-clause BSD style license - see LICENSE.rst + +import astropy.units as u +from astropy.time import Time +import json +from collections import OrderedDict + +from ..query import BaseQuery +from ..utils import async_to_sync +from . import conf + +__all__ = ['AstInfo', 'AstInfoClass'] + + +@async_to_sync +class AstInfoClass(BaseQuery): + + """ + A class for querying Lowell Observatory's `astorbDB + `_ service. + """ + # Not all the methods below are necessary but these cover most of the common + # cases, new methods may be added if necessary, follow the guidelines at + # + + URL = conf.server + TIMEOUT = conf.timeout + + # internal flag whether to return the raw reponse + _return_raw = False + + # actual query uri + _uri = None + + def designations_async(self, object_name, *, + get_raw_response=False, + get_uri=False, + cache=True): + """ + This method uses a REST interface to query the `Lowell Observatory + astorbDB database `_ for designation + data for a single object and returns a dictionary from JSON results + + Parameters + ---------- + object_name : str + name of the identifier to query. + + Returns + ------- + res : A dictionary holding available designation data + + Examples + -------- + >>> from astroquery.astorbdb import AstInfo + >>> designations = AstInfo.designations('Beagle') + >>> print(designations) + OrderedDict({'alternate_designations': ['1954 HJ', ...], 'name': 'Beagle', 'number': 656, ...}) + """ + + self.query_type = 'designations' + + response = self._request('GET', + url=self.URL + object_name + '/designations', + timeout=self.TIMEOUT, cache=cache) + + if get_raw_response: + self._return_raw = True + + if get_uri: + self._uri = response.url + + return response + + def elements_async(self, object_name, *, + get_raw_response=False, + get_uri=False, + cache=True): + """ + This method uses a REST interface to query the `Lowell Observatory + astorbDB database `_ for orbital element + data for a single object and returns a dictionary from JSON results + + Parameters + ---------- + object_name : str + name of the identifier to query. + + Returns + ------- + res : A dictionary holding available orbital element data + + Examples + -------- + >>> from astroquery.astorbdb import AstInfo + >>> elements = AstInfo.elements('Beagle') + >>> print(elements) + OrderedDict({'a': , 'aphelion_dist': , ...}) + """ + + self.query_type = 'elements' + + response = self._request('GET', + url=self.URL + object_name + '/elements', + timeout=self.TIMEOUT, cache=cache) + + if get_raw_response: + self._return_raw = True + + if get_uri: + self._uri = response.url + + return response + + def orbit_async(self, object_name, *, + get_raw_response=False, + get_uri=False, + cache=True): + """ + This method uses a REST interface to query the `Lowell Observatory + astorbDB database `_ for orbit + data for a single object and returns a dictionary from JSON results + + Parameters + ---------- + object_name : str + name of the identifier to query. + + Returns + ------- + res : A dictionary holding available orbit data + + Examples + -------- + >>> from astroquery.astorbdb import AstInfo + >>> orbit = AstInfo.orbit('Beagle') + >>> print(orbit) + OrderedDict({'a1con': , 'a2con': , ...}) + """ + + self.query_type = 'orbit' + + response = self._request('GET', + url=self.URL + object_name + '/orbit', + timeout=self.TIMEOUT, cache=cache) + + if get_raw_response: + self._return_raw = True + + if get_uri: + self._uri = response.url + + return response + + def albedos_async(self, object_name, *, + get_raw_response=False, + get_uri=False, + cache=True): + """ + This method uses a REST interface to query the `Lowell Observatory + astorbDB database `_ for albedo + data for a single object and returns a dictionary from JSON results + + Parameters + ---------- + object_name : str + name of the identifier to query. + + Returns + ------- + res : A dictionary holding available albedo data + + Examples + -------- + >>> from astroquery.astorbdb import AstInfo + >>> albedos = AstInfo.albedos('Beagle') + >>> print(albedos) + [{'albedo': 0.065, 'albedo_error_lower': -0.002, ..., 'survey_name': 'Usui et al. (2011)'}, + {'albedo': 0.0625, 'albedo_error_lower': -0.015, ..., 'survey_name': 'Infrared Astronomical Satellite (IRAS)'}, + ...] + """ + + self.query_type = 'albedos' + + response = self._request('GET', + url=self.URL + object_name + '/data/albedos', + timeout=self.TIMEOUT, cache=cache) + + if get_raw_response: + self._return_raw = True + + if get_uri: + self._uri = response.url + + return response + + def colors_async(self, object_name, *, + get_raw_response=False, + get_uri=False, + cache=True): + """ + This method uses a REST interface to query the `Lowell Observatory + astorbDB database `_ for color + data for a single object and returns a dictionary from JSON results + + Parameters + ---------- + object_name : str + name of the identifier to query. + + Returns + ------- + res : A dictionary holding available color data + + Examples + -------- + >>> from astroquery.astorbdb import AstInfo + >>> colors = AstInfo.colors('Beagle') + >>> print(colors) + [{..., 'color': 0.431, 'color_error': 0.035, ..., 'sys_color': 'J-H'}, + {..., 'color': 0.076, 'color_error': 0.041, ..., 'sys_color': 'H-K'}, + ...] + """ + + self.query_type = 'colors' + + response = self._request('GET', + url=self.URL + object_name + '/data/colors', + timeout=self.TIMEOUT, cache=cache) + + if get_raw_response: + self._return_raw = True + + if get_uri: + self._uri = response.url + + return response + + def taxonomies_async(self, object_name, *, + get_raw_response=False, + get_uri=False, + cache=True): + """ + This method uses a REST interface to query the `Lowell Observatory + astorbDB database `_ for taxonomy + data for a single object and returns a dictionary from JSON results + + Parameters + ---------- + object_name : str + name of the identifier to query. + + Returns + ------- + res : A dictionary holding available taxonomy data + + Examples + -------- + >>> from astroquery.astorbdb import AstInfo + >>> taxonomies = AstInfo.taxonomies('Beagle') + >>> print(taxonomies) + [{'citation_bibcode': '2011PDSS..145.....H', ..., 'survey_name': 'Carvano et al. (2010)', 'taxonomy': 'C', ...}, + {'citation_bibcode': '2013Icar..226..723D', ..., 'survey_name': 'DeMeo et al. (2013)', 'taxonomy': 'C', ...}] + """ + + self.query_type = 'taxonomies' + + response = self._request('GET', + url=self.URL + object_name + '/data/taxonomies', + timeout=self.TIMEOUT, cache=cache) + + if get_raw_response: + self._return_raw = True + + if get_uri: + self._uri = response.url + + return response + + def lightcurves_async(self, object_name, *, + get_raw_response=False, + get_uri=False, + cache=True): + """ + This method uses a REST interface to query the `Lowell Observatory + astorbDB database `_ for lightcurve + data for a single object and returns a dictionary from JSON results + + Parameters + ---------- + object_name : str + name of the identifier to query. + + Returns + ------- + res : A dictionary holding available lightcurve data + + Examples + -------- + >>> from astroquery.astorbdb import AstInfo + >>> lightcurves = AstInfo.lightcurves('Beagle') + >>> print(lightcurves) + [{..., 'amp_max': , 'amp_min': , ..., 'period': , ...}] + """ + + self.query_type = 'lightcurves' + + response = self._request('GET', + url=self.URL + object_name + '/data/lightcurves', + timeout=self.TIMEOUT, cache=cache) + + if get_raw_response: + self._return_raw = True + + if get_uri: + self._uri = response.url + + return response + + def dynamicalfamily_async(self, object_name, *, + get_raw_response=False, + get_uri=False, + cache=True): + """ + This method uses a REST interface to query the `Lowell Observatory + astorbDB database `_ for dynamical family + data for a single object and returns a dictionary from JSON results + + Parameters + ---------- + object_name : str + name of the identifier to query. + + Returns + ------- + res : A dictionary holding available dynamical family data + + Examples + -------- + >>> from astroquery.astorbdb import AstInfo + >>> dynamicalfamily = AstInfo.dynamicalfamily('Beagle') + >>> print(dynamicalfamily) + [{'citation_bibcode': '2015PDSS..234.....N', ..., 'family': 'Themis', ...}, + {'citation_bibcode': '2015PDSS..234.....N', ..., 'family': 'Beagle', ...}] + """ + + self.query_type = 'dynamicalfamily' + + response = self._request('GET', + url=self.URL + object_name + '/data/dynamical-family', + timeout=self.TIMEOUT, cache=cache) + + if get_raw_response: + self._return_raw = True + + if get_uri: + self._uri = response.url + + return response + + def escaperoutes_async(self, object_name, *, + get_raw_response=False, + get_uri=False, + cache=True): + """ + This method uses a REST interface to query the `Lowell Observatory + astorbDB database `_ for NEO escape route + data for a single object and returns a dictionary from JSON results + + Parameters + ---------- + object_name : str + name of the identifier to query. + + Returns + ------- + res : A dictionary holding available NEO escape route data + + Examples + -------- + >>> from astroquery.astorbdb import AstInfo + >>> escaperoutes = AstInfo.escaperoutes('3552') + >>> print(escaperoutes) + [{'citation_bibcode': '2018Icar..312..181G', ..., 'dp21_complex': 0.03695, 'dp31_complex': 0.00105, ...}] + """ + + self.query_type = 'escaperoutes' + + response = self._request('GET', + url=self.URL + object_name + '/data/escape-routes', + timeout=self.TIMEOUT, cache=cache) + + if get_raw_response: + self._return_raw = True + + if get_uri: + self._uri = response.url + + return response + + def all_astinfo_async(self, object_name, *, + get_raw_response=False, + get_uri=False, + cache=True): + """ + This method uses REST interfaces to query the `Lowell Observatory + astorbDB database `_ for all AstInfo + data for a single object and returns a dictionary from JSON results + + Parameters + ---------- + object_name : str + name of the identifier to query. + + Returns + ------- + res : A dictionary holding available AstInfo data + + Examples + -------- + >>> from astroquery.astorbdb import AstInfo + >>> all_astinfo = AstInfo.all_astinfo('Beagle') + >>> print(all_astinfo) + + OrderedDict({ + 'designations': OrderedDict({'alternate_designations': ['1954 HJ', ...], 'name': 'Beagle', ...}), + 'elements': OrderedDict({'a': , 'aphelion_dist': , ...}), + 'orbit': OrderedDict({'a1con': , 'a2con': , ...}), + 'albedos': [{'albedo': 0.065, ..., 'survey_name': 'Usui et al. (2011)'}, + {'albedo': 0.0625, ..., 'survey_name': 'Infrared Astronomical Satellite (IRAS)'}, + ...], + 'colors': [{..., 'color': 0.431, 'color_error': 0.035, ..., 'sys_color': 'J-H'}, + {..., 'color': 0.076, 'color_error': 0.041, ..., 'sys_color': 'H-K'}, + ...], + 'taxonomies': [{..., 'survey_name': 'Carvano et al. (2010)', 'taxonomy': 'C', ...}, + {..., 'survey_name': 'DeMeo et al. (2013)', 'taxonomy': 'C', ...}], + 'lightcurves': [{..., 'amp_max': , ..., 'period': , ...}], + 'dynamicalfamily': [{'citation_bibcode': '2015PDSS..234.....N', ..., 'family': 'Themis', ...}, + {'citation_bibcode': '2015PDSS..234.....N', ..., 'family': 'Beagle', ...}], + 'escaperoutes': [] + }) + """ + + self.query_type = 'all_astinfo' + + response = {} + + response['designations'] = self._request('GET', + url=self.URL + object_name + '/designations', + timeout=self.TIMEOUT, cache=cache) + + response['elements'] = self._request('GET', + url=self.URL + object_name + '/elements', + timeout=self.TIMEOUT, cache=cache) + + response['orbit'] = self._request('GET', + url=self.URL + object_name + '/orbit', + timeout=self.TIMEOUT, cache=cache) + + response['albedos'] = self._request('GET', + url=self.URL + object_name + '/data/albedos', + timeout=self.TIMEOUT, cache=cache) + + response['colors'] = self._request('GET', + url=self.URL + object_name + '/data/colors', + timeout=self.TIMEOUT, cache=cache) + + response['taxonomies'] = self._request('GET', + url=self.URL + object_name + '/data/taxonomies', + timeout=self.TIMEOUT, cache=cache) + + response['lightcurves'] = self._request('GET', + url=self.URL + object_name + '/data/lightcurves', + timeout=self.TIMEOUT, cache=cache) + + response['dynamicalfamily'] = self._request('GET', + url=self.URL + object_name + '/data/dynamical-family', + timeout=self.TIMEOUT, cache=cache) + + response['escaperoutes'] = self._request('GET', + url=self.URL + object_name + '/data/escape-routes', + timeout=self.TIMEOUT, cache=cache) + + if get_raw_response: + self._return_raw = True + + if get_uri: + self._uri = {'designations': response['designations'].url, + 'elements': response['elements'].url, + 'orbit': response['orbit'].url, + 'albedos': response['albedos'].url, + 'colors': response['colors'].url, + 'taxonomies': response['taxonomies'].url, + 'lightcurves': response['lightcurves'].url, + 'dynamicalfamily': response['dynamicalfamily'].url, + 'escaperoutes': response['escaperoutes'].url + } + + return response + + def _parse_result(self, response, *, verbose=None): + """ + Parser for astorbDB AstInfo request results + """ + + if self._return_raw: + return response.text + + # decode json response from Lowell astorbDB into ascii + try: + if self.query_type == 'all_astinfo': + src = OrderedDict() + for key in response: + src[key] = OrderedDict(json.loads(response[key].text)) + else: + src = OrderedDict(json.loads(response.text)) + except ValueError: + raise ValueError('Server response not readable.') + + if self.query_type == 'designations': + src = self._process_data_designations(src) + + if self.query_type == 'elements': + src = self._process_data_elements(src) + + if self.query_type == 'orbit': + src = self._process_data_orbit(src) + + if self.query_type == 'albedos': + src = self._process_data_albedos(src) + + if self.query_type == 'colors': + src = self._process_data_colors(src) + + if self.query_type == 'taxonomies': + src = self._process_data_taxonomies(src) + + if self.query_type == 'lightcurves': + src = self._process_data_lightcurves(src) + + if self.query_type == 'dynamicalfamily': + src = self._process_data_dynamicalfamily(src) + + if self.query_type == 'escaperoutes': + src = self._process_data_escaperoutes(src) + + if self.query_type == 'all_astinfo': + src['designations'] = self._process_data_designations(src['designations']) + src['elements'] = self._process_data_elements(src['elements']) + src['orbit'] = self._process_data_orbit(src['orbit']) + src['albedos'] = self._process_data_albedos(src['albedos']) + src['colors'] = self._process_data_colors(src['colors']) + src['taxonomies'] = self._process_data_taxonomies(src['taxonomies']) + src['lightcurves'] = self._process_data_lightcurves(src['lightcurves']) + src['dynamicalfamily'] = self._process_data_dynamicalfamily(src['dynamicalfamily']) + src['escaperoutes'] = self._process_data_escaperoutes(src['escaperoutes']) + + # add query uri, if desired + if self._uri is not None: + src['query_uri'] = self._uri + + return src + + def _process_data_designations(self, src): + """ + internal routine to process raw data in OrderedDict format + + """ + + if 'designations' in src: + src = OrderedDict(src['designations']) + + return src + + def _process_data_elements(self, src): + """ + internal routine to process raw data in OrderedDict format, must + be able to work recursively + + """ + + if 'elements' in src: + src = OrderedDict(src['elements']) + src['a'] = u.Quantity(src['a'], u.au) + src['aphelion_dist'] = u.Quantity(src['aphelion_dist'], u.au) + if src['delta_v'] is not None: + src['delta_v'] = u.Quantity(src['delta_v'], u.km/u.s) + src['ecc_anomaly'] = u.Quantity(src['ecc_anomaly'], u.deg) + src['epoch'] = Time(src['epoch'], format='isot', scale='utc') + src['h'] = u.Quantity(src['h'], u.mag) + src['i'] = u.Quantity(src['m'], u.deg) + src['long_of_perihelion'] = u.Quantity(src['long_of_perihelion'], u.deg) + src['m'] = u.Quantity(src['m'], u.deg) + src['moid_earth'] = u.Quantity(src['moid_earth'], u.au) + src['moid_jupiter'] = u.Quantity(src['moid_jupiter'], u.au) + src['moid_mars'] = u.Quantity(src['moid_mars'], u.au) + src['moid_mercury'] = u.Quantity(src['moid_mercury'], u.au) + src['moid_neptune'] = u.Quantity(src['moid_neptune'], u.au) + src['moid_saturn'] = u.Quantity(src['moid_saturn'], u.au) + src['moid_uranus'] = u.Quantity(src['moid_uranus'], u.au) + src['moid_venus'] = u.Quantity(src['moid_venus'], u.au) + src['node'] = u.Quantity(src['node'], u.deg) + src['peri'] = u.Quantity(src['peri'], u.deg) + src['q'] = u.Quantity(src['q'], u.au) + src['r'] = u.Quantity(src['r'], u.au) + src['true_anomaly'] = u.Quantity(src['true_anomaly'], u.deg) + src['x'] = u.Quantity(src['x'], u.au) + src['y'] = u.Quantity(src['y'], u.au) + src['z'] = u.Quantity(src['z'], u.au) + + return src + + def _process_data_orbit(self, src): + """ + internal routine to process raw data in OrderedDict format, must + be able to work recursively + + """ + + if 'orbit' in src: + src = OrderedDict(src['orbit']) + src['a1con'] = u.Quantity(src['a1con'], u.au/(u.d ** 2)) + src['a2con'] = u.Quantity(src['a2con'], u.au/(u.d ** 2)) + src['a3con'] = u.Quantity(src['a3con'], u.au/(u.d ** 2)) + src['arc'] = u.Quantity(src['arc'], u.yr) + + return src + + def _process_data_albedos(self, src): + """ + internal routine to process raw data in Dict format + + """ + + if 'albedos' in src: + src = src['albedos'] + for i in range(len(src)): + src[i]['diameter'] = u.Quantity(src[i]['diameter'], u.km) + src[i]['diameter_error_lower'] = u.Quantity(src[i]['diameter_error_lower'], u.km) + src[i]['diameter_error_upper'] = u.Quantity(src[i]['diameter_error_upper'], u.km) + + return src + + def _process_data_colors(self, src): + """ + internal routine to process raw data in Dict format + + """ + + if 'colors' in src: + src = src['colors'] + for i in range(len(src)): + src[i]['jd'] = Time(src[i]['jd'], format='jd', scale='utc') + + return src + + def _process_data_taxonomies(self, src): + """ + internal routine to process raw data in OrderedDict format, must + be able to work recursively + + """ + + if 'taxonomies' in src: + src = src['taxonomies'] + + return src + + def _process_data_lightcurves(self, src): + """ + internal routine to process raw data in OrderedDict format, must + be able to work recursively + + """ + + if 'lightcurves' in src: + src = src['lightcurves'] + for i in range(len(src)): + if src[i]['amp_max'] is not None: + src[i]['amp_max'] = u.Quantity(src[i]['amp_max'], u.mag) + if src[i]['amp_min'] is not None: + src[i]['amp_min'] = u.Quantity(src[i]['amp_min'], u.mag) + src[i]['period'] = u.Quantity(src[i]['period'], u.h) + + return src + + def _process_data_dynamicalfamily(self, src): + """ + internal routine to process raw data in OrderedDict format, must + be able to work recursively + + """ + + if 'dynamical-family' in src: + src = src['dynamical-family'] + + return src + + def _process_data_escaperoutes(self, src): + """ + internal routine to process raw data in OrderedDict format, must + be able to work recursively + + """ + + if 'escape-routes' in src: + src = src['escape-routes'] + for i in range(len(src)): + src[i]['epoch'] = Time(src[i]['epoch'], format='isot', scale='utc') + + return src + + +AstInfo = AstInfoClass() + +# once your class is done, tests should be written +# See ./tests for examples on this + +# Next you should write the docs in astroquery/docs/module_name +# using Sphinx. diff --git a/astroquery/astorbdb/tests/__init__.py b/astroquery/astorbdb/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/astroquery/astorbdb/tests/data/dummy.dat b/astroquery/astorbdb/tests/data/dummy.dat new file mode 100644 index 0000000000..aa5bd30df5 --- /dev/null +++ b/astroquery/astorbdb/tests/data/dummy.dat @@ -0,0 +1,2 @@ +this is a dummy data file. +Similarly include xml, html, fits and other data files for tests diff --git a/astroquery/astorbdb/tests/setup_package.py b/astroquery/astorbdb/tests/setup_package.py new file mode 100644 index 0000000000..72b8669485 --- /dev/null +++ b/astroquery/astorbdb/tests/setup_package.py @@ -0,0 +1,15 @@ +# Licensed under a 3-clause BSD style license - see LICENSE.rst + + +import os + + +# setup paths to the test data +# can specify a single file or a list of files +def get_package_data(): + paths = [os.path.join('data', '*.dat'), + os.path.join('data', '*.xml'), + ] # etc, add other extensions + # you can also enlist files individually by names + # finally construct and return a dict for the sub module + return {'astroquery.template_module.tests': paths} diff --git a/astroquery/astorbdb/tests/test_module.py b/astroquery/astorbdb/tests/test_module.py new file mode 100644 index 0000000000..f2574589e1 --- /dev/null +++ b/astroquery/astorbdb/tests/test_module.py @@ -0,0 +1,80 @@ +# Licensed under a 3-clause BSD style license - see LICENSE.rst + +# astroquery uses the pytest framework for testing +# this is already available in astropy and does +# not require a separate install. Import it using: +import pytest + +# It would be best if tests are separated in two +# modules. This module performs tests on local data +# by mocking HTTP requests and responses. To test the +# same functions on the remote server, put the relevant +# tests in the 'test_module_remote.py' + +# Now import other commonly used modules for tests +import os + +from astropy.table import Table +import astropy.coordinates as coord +import astropy.units as u + +from astroquery.utils.mocks import MockResponse + +# finally import the module which is to be tested +# and the various configuration items created +from ... import template_module +from ...template_module import conf + +# Local tests should have the corresponding data stored +# in the ./data folder. This is the actual HTTP response +# one would expect from the server when a valid query is made. +# Its best to keep the data file small, so that testing is +# quicker. When running tests locally the stored data is used +# to mock the HTTP requests and response part of the query +# thereby saving time and bypassing unreliability for +# an actual remote network query. + +DATA_FILES = {'GET': + # You might have a different response for each URL you're + # querying: + {'http://dummy_server_mirror_1': + 'dummy.dat'}} + + +# ./setup_package.py helps the test function locate the data file +# define a function that can construct the full path to the file in the +# ./data directory: +def data_path(filename): + data_dir = os.path.join(os.path.dirname(__file__), 'data') + return os.path.join(data_dir, filename) + + +# define a monkeypatch replacement request function that returns the +# dummy HTTP response for the dummy 'get' function, by +# reading in data from some data file: +def nonremote_request(self, request_type, url, **kwargs): + # kwargs are ignored in this case, but they don't have to be + # (you could use them to define which data file to read) + with open(data_path(DATA_FILES[request_type][url]), 'rb') as f: + response = MockResponse(content=f.read(), url=url) + return response + + +# use a pytest fixture to create a dummy 'requests.get' function, +# that mocks(monkeypatches) the actual 'requests.get' function: +@pytest.fixture +def patch_request(request): + mp = request.getfixturevalue("monkeypatch") + + mp.setattr(template_module.core.TemplateClass, '_request', + nonremote_request) + return mp + + +# finally test the methods using the mock HTTP response +def test_query_object(patch_request): + result = template_module.core.TemplateClass().query_object('m1') + assert isinstance(result, Table) + +# similarly fill in tests for each of the methods +# look at tests in existing modules for more examples diff --git a/astroquery/astorbdb/tests/test_module_remote.py b/astroquery/astorbdb/tests/test_module_remote.py new file mode 100644 index 0000000000..ca7ba46800 --- /dev/null +++ b/astroquery/astorbdb/tests/test_module_remote.py @@ -0,0 +1,16 @@ +# Licensed under a 3-clause BSD style license - see LICENSE.rst + + +# performs similar tests as test_module.py, but performs +# the actual HTTP request rather than monkeypatching them. +# should be disabled or enabled at will - use the +# remote_data decorator from astropy: + +import pytest + + +@pytest.mark.remote_data +class TestTemplateClass: + # now write tests for each method here + def test_this(self): + pass