Skip to content

Commit

Permalink
Merge branch 'main' into mivot-writer
Browse files Browse the repository at this point in the history
  • Loading branch information
lmichel authored Jan 21, 2025
2 parents c39489b + 323fae4 commit 3e9c6a4
Show file tree
Hide file tree
Showing 38 changed files with 224 additions and 176 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci_devtests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
run: tox -e py312-test-devdeps-alldeps-cov

- name: Upload coverage to codecov
uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238 # v4.6.0
uses: codecov/codecov-action@1e68e06f1dbfde0e4cefc87efeba9e4643565303 # v5.1.2
with:
file: ./coverage.xml
verbose: true
Expand Down
20 changes: 10 additions & 10 deletions .github/workflows/ci_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ jobs:
fail-fast: false
matrix:
include:
- name: py38 oldest dependencies, Linux
python-version: '3.8'
tox_env: py38-test-oldestdeps-alldeps
- name: py39 mandatory dependencies only, Linux
- name: py39 oldest dependencies, Linux
python-version: '3.9'
tox_env: py39-test
tox_env: py39-test-oldestdeps-alldeps
- name: py310 mandatory dependencies only, Linux
python-version: '3.10'
tox_env: py310-test
- name: py311 with online tests, Linux
python-version: '3.11'
tox_env: py311-test-alldeps-online
Expand Down Expand Up @@ -63,11 +63,11 @@ jobs:
- name: Set up Python
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
with:
python-version: '3.10'
python-version: '3.12'
- name: Install tox
run: python -m pip install --upgrade tox
- name: Python 3.10 with latest astropy
run: tox -e py310-test-alldeps
- name: Python 3.12 with latest astropy
run: tox -e py312-test-alldeps


stylecheck:
Expand All @@ -76,10 +76,10 @@ jobs:
fail-fast: false
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Python 3.8
- name: Set up Python 3.12
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
with:
python-version: 3.8
python-version: '3.12'
- name: Install tox
run: python -m pip install --upgrade tox
- name: Check codestyle
Expand Down
3 changes: 3 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Enhancements and Fixes
- Extending the MIVOT module with the ability to build annotations component by component
and put them into a VOTable. [#627]

- Make deletion of TAP jobs optional via a new ``delete`` kwarg. [#640]

Deprecations and Removals
-------------------------
Expand All @@ -22,6 +23,8 @@ Bug Fixes

- Fix string literal generation for SQL query when using numpy >=2.0. [#624]

- Switch to do minimal VOSI tables downloads for TAP metadata. [#634]


1.6 (2024-11-01)
================
Expand Down
14 changes: 7 additions & 7 deletions docs/dal/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ to see the tables available on the Simbad TAP service, say:

>>> simbad = vo.dal.TAPService("http://simbad.cds.unistra.fr/simbad/sim-tap")
>>> print([tab_name for tab_name in simbad.tables.keys()]) # doctest: +IGNORE_WARNINGS
['TAP_SCHEMA.schemas', 'TAP_SCHEMA.tables', 'TAP_SCHEMA.columns', 'TAP_SCHEMA.keys', ... 'mesVelocities', 'mesXmm', 'otypedef', 'otypes', 'ref']
['TAP_SCHEMA.schemas', 'TAP_SCHEMA.tables', ... 'otypedef', 'otypes', 'ref']


If you know a TAP service's access URL, you can directly pass it to
Expand Down Expand Up @@ -264,7 +264,7 @@ starting it, it creates a new object :py:class:`~pyvo.dal.AsyncTAPJob`.
.. doctest-remote-data::

>>> job.url
'http://dc.zah.uni-heidelberg.de/__system__/tap/run/async/...'
'http://dc.g-vo.org/__system__/tap/run/async/...'

The job URL mentioned before is available in the ``url`` attribute.
Clicking on the URL leads you to the query itself, where you can check
Expand Down Expand Up @@ -818,11 +818,11 @@ previews:
... ).run_sync("select top 5 * from califadr3.cubes order by califaid")
>>> for dl in rows.iter_datalinks(): # doctest: +IGNORE_WARNINGS
... print(next(dl.bysemantics("#preview"))["access_url"])
http://dc.zah.uni-heidelberg.de/getproduct/califa/datadr3/V1200/IC5376.V1200.rscube.fits?preview=True
http://dc.zah.uni-heidelberg.de/getproduct/califa/datadr3/COMB/IC5376.COMB.rscube.fits?preview=True
http://dc.zah.uni-heidelberg.de/getproduct/califa/datadr3/V500/IC5376.V500.rscube.fits?preview=True
http://dc.zah.uni-heidelberg.de/getproduct/califa/datadr3/COMB/UGC00005.COMB.rscube.fits?preview=True
http://dc.zah.uni-heidelberg.de/getproduct/califa/datadr3/V1200/UGC00005.V1200.rscube.fits?preview=True
http://dc.g-vo.org/getproduct/califa/datadr3/V1200/IC5376.V1200.rscube.fits?preview=True
http://dc.g-vo.org/getproduct/califa/datadr3/COMB/IC5376.COMB.rscube.fits?preview=True
http://dc.g-vo.org/getproduct/califa/datadr3/V500/IC5376.V500.rscube.fits?preview=True
http://dc.g-vo.org/getproduct/califa/datadr3/COMB/UGC00005.COMB.rscube.fits?preview=True
http://dc.g-vo.org/getproduct/califa/datadr3/V1200/UGC00005.V1200.rscube.fits?preview=True

The call to ``next`` in this example picks the first link marked
*preview*. For previews, this may be enough, but in general there can
Expand Down
2 changes: 1 addition & 1 deletion docs/registry/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ RegTAP services using:
>>> res = registry.search(datamodel="regtap")
>>> print("\n".join(sorted(r.get_interface(service_type="tap", lax=True).access_url
... for r in res)))
http://dc.zah.uni-heidelberg.de/tap
http://dc.g-vo.org/tap
http://gavo.aip.de/tap
http://voparis-rr.obspm.fr/tap
https://vao.stsci.edu/RegTAP/TapService.aspx
Expand Down
2 changes: 1 addition & 1 deletion pyvo/auth/authsession.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class AuthSession:
"""

def __init__(self):
super(AuthSession, self).__init__()
super().__init__()
self.credentials = CredentialStore()
self._auth_urls = AuthURLs()

Expand Down
5 changes: 2 additions & 3 deletions pyvo/auth/authurls.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,9 @@ def sort_by_len(x):
# the longest URLs (the most specific ones, if
# there is a tie) are used to determine the
# auth method.
for url, method in sorted(self.base_urls.items(),
yield from sorted(self.base_urls.items(),
key=sort_by_len,
reverse=True):
yield url, method
reverse=True)

def __repr__(self):
urls = []
Expand Down
2 changes: 1 addition & 1 deletion pyvo/auth/credentialstore.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
__all__ = ["CredentialStore"]


class CredentialStore(object):
class CredentialStore:
"""
The credential store takes user credentials, and uses them
to create appropriate requests sessions for dispatching
Expand Down
6 changes: 3 additions & 3 deletions pyvo/dal/adhoc.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ def get_adhocservice_by_ivoid(self, ivo_id):
):
return adhocservice
raise DALServiceError(
"No Adhoc Service with ivo-id {}!".format(ivo_id))
f"No Adhoc Service with ivo-id {ivo_id}!")

def get_adhocservice_by_id(self, id_):
"""
Expand All @@ -162,7 +162,7 @@ def get_adhocservice_by_id(self, id_):
if adhocservice.ID == id_:
return adhocservice
raise DALServiceError(
"No Adhoc Service with service_def id {}!".format(id_))
f"No Adhoc Service with service_def id {id_}!")


class DatalinkResultsMixin(AdhocServiceResultsMixin):
Expand Down Expand Up @@ -683,7 +683,7 @@ def bysemantics(self, semantics, *, include_narrower=True):
additional_terms.extend(voc["terms"][term]["narrower"])
core_terms = core_terms + additional_terms

semantics = set("#" + term for term in core_terms) | set(other_terms)
semantics = {"#" + term for term in core_terms} | set(other_terms)
for record in self:
if record.semantics in semantics:
yield record
Expand Down
6 changes: 3 additions & 3 deletions pyvo/dal/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def __str__(self):
return self._reason

def __repr__(self):
return "{}: {}".format(self._typeName(self), self._reason)
return f"{self._typeName(self)}: {self._reason}"

@property
def reason(self):
Expand Down Expand Up @@ -188,13 +188,13 @@ def from_except(cls, exc, url=None):
code = response.status_code
content_type = response.headers.get('content-type', None)
if content_type and 'text/plain' in content_type:
message = '{} for {}'.format(response.text, url)
message = f'{response.text} for {url}'

# TODO votable handling

return DALServiceError(message, code, exc, url)
elif isinstance(exc, Exception):
return DALServiceError("{}: {}".format(cls._typeName(exc), str(exc)),
return DALServiceError(f"{cls._typeName(exc)}: {str(exc)}",
cause=exc, url=url)
else:
raise TypeError("from_except: expected Exception")
Expand Down
2 changes: 1 addition & 1 deletion pyvo/dal/mimetype.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def mime_object_maker(url, mimetype, *, session=None):
params = pp[1:]
mtype = [x.strip() for x in full_type.split('/')] if '/' in full_type else None
if not mtype or len(mtype) > 2:
raise ValueError("Can't parse mimetype \"{}\"".format(full_type))
raise ValueError(f"Can't parse mimetype \"{full_type}\"")

if mtype[0] == 'text':
return session.get(url).text
Expand Down
25 changes: 12 additions & 13 deletions pyvo/dal/params.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def find_param_by_keyword(keyword, params):
if keyword in params:
return params[keyword]

raise KeyError('No param named {} defined'.format(keyword))
raise KeyError(f'No param named {keyword} defined')


registry = dict()
Expand Down Expand Up @@ -332,7 +332,7 @@ def _validate_pos(self, pos):
else:
radius = pos[1]
if radius <= 0 * u.deg or radius.to(u.deg) > 90 * u.deg:
raise ValueError('Invalid circle radius: {}'.format(radius))
raise ValueError(f'Invalid circle radius: {radius}')
elif len(pos) == 3:
self._validate_ra(pos[0])
self._validate_dec(pos[1])
Expand All @@ -341,7 +341,7 @@ def _validate_pos(self, pos):
else:
radius = pos[2]
if radius <= 0 * u.deg or radius.to(u.deg) > 90 * u.deg:
raise ValueError('Invalid circle radius: {}'.format(radius))
raise ValueError(f'Invalid circle radius: {radius}')
elif len(pos) == 4:
ra_min = pos[0] if isinstance(pos[0], Quantity) else pos[0] * u.deg
ra_max = pos[1] if isinstance(pos[1], Quantity) else pos[1] * u.deg
Expand All @@ -367,16 +367,14 @@ def _validate_pos(self, pos):
self._validate_ra(m)

def _validate_ra(self, ra):
if not isinstance(ra, Quantity):
ra = ra * u.deg
ra = Quantity(ra, u.deg)
if ra.to(u.deg).value < 0 or ra.to(u.deg).value > 360.0:
raise ValueError('Invalid ra: {}'.format(ra))
raise ValueError(f'Invalid ra: {ra}')

def _validate_dec(self, dec):
if not isinstance(dec, Quantity):
dec = dec * u.deg
dec = Quantity(dec, u.deg)
if dec.to(u.deg).value < -90.0 or dec.to(u.deg).value > 90.0:
raise ValueError('Invalid dec: {}'.format(dec))
raise ValueError(f'Invalid dec: {dec}')


class IntervalQueryParam(AbstractDalQueryParam):
Expand Down Expand Up @@ -415,17 +413,18 @@ def get_dal_format(self, val):
low, high))
if self._unit:
if not isinstance(low, Quantity):
low = low * self._unit
low = u.Quantity(low, self._unit)
low = low.to(self._unit, equivalencies=self._equivalencies).value

if not isinstance(high, Quantity):
high = high * self._unit
high = Quantity(high, self._unit)
high = high.to(self._unit, equivalencies=self._equivalencies).value

if low > high:
# interval could become invalid during transform (e.g. GHz->m)
low, high = high, low

return '{} {}'.format(low, high)
return f'{low} {high}'


class TimeQueryParam(AbstractDalQueryParam):
Expand Down Expand Up @@ -454,7 +453,7 @@ def get_dal_format(self, val):
raise ValueError('Invalid time interval: min({}) > max({})'.format(
min_time, max_time
))
return '{} {}'.format(min_time.mjd, max_time.mjd)
return f'{min_time.mjd} {max_time.mjd}'


class EnumQueryParam(AbstractDalQueryParam):
Expand Down
16 changes: 8 additions & 8 deletions pyvo/dal/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import re
import requests
from collections.abc import Mapping
from io import BytesIO
from io import BytesIO, StringIO

import collections

Expand Down Expand Up @@ -129,7 +129,7 @@ def describe(self):
"""
describe the general information about the DAL service
"""
print('DAL Service at {}'.format(self.baseurl))
print(f'DAL Service at {self.baseurl}')


class DALQuery(dict):
Expand Down Expand Up @@ -551,7 +551,7 @@ def getcolumn(self, name):

return self.resultstable.array[name]
except KeyError:
raise KeyError("No such column: {}".format(name))
raise KeyError(f"No such column: {name}")

def getrecord(self, index):
"""
Expand Down Expand Up @@ -686,7 +686,7 @@ def __getitem__(self, key):

return self._mapping[key]
except KeyError:
raise KeyError("No such column: {}".format(key))
raise KeyError(f"No such column: {key}")

def __iter__(self):
return iter(self._mapping)
Expand Down Expand Up @@ -889,7 +889,7 @@ def make_dataset_filename(self, *, dir=".", base=None, ext=None):
if not os.path.exists(dir):
os.mkdir(dir)
if not os.path.isdir(dir):
raise ValueError("{}: not a directory".format(dir))
raise ValueError(f"{dir}: not a directory")

if not base:
base = self.suggest_dataset_basename()
Expand All @@ -904,7 +904,7 @@ def make_dataset_filename(self, *, dir=".", base=None, ext=None):
n = self._dsname_no

def mkpath(i):
return os.path.join(dir, "{}-{}.{}".format(base, i, ext))
return os.path.join(dir, f"{base}-{i}.{ext}")

if n > 0:
# find the last file written of the form, base-n.ext
Expand All @@ -914,7 +914,7 @@ def mkpath(i):
n += 1
if n == 0:
# never wrote a file of form, base-n.ext; try base.ext
path = os.path.join(dir, "{}.{}".format(base, ext))
path = os.path.join(dir, f"{base}.{ext}")
if not os.path.exists(path):
return path
n += 1
Expand Down Expand Up @@ -1042,7 +1042,7 @@ def fileobj(self):

return fileobj

elif isinstance(self._content, BytesIO):
elif isinstance(self._content, (BytesIO, StringIO)):
return self._content

elif isinstance(self._content, DALResults):
Expand Down
2 changes: 1 addition & 1 deletion pyvo/dal/sia2.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ def __init__(self, url, pos=None, *, band=None, time=None, pol=None,
custom_arg = []
for kw in _tolist(value):
if isinstance(kw, tuple):
val = '{} {}'.format(kw[0], kw[1])
val = f'{kw[0]} {kw[1]}'
else:
val = str(kw)
custom_arg.append(val)
Expand Down
Loading

0 comments on commit 3e9c6a4

Please sign in to comment.