BUG: notifyWarning is undefined
@msdemlei - I'm not sure which warning you meant to raise in https://github.com/astropy/pyvo/blob/main/pyvo/utils/vocabularies.py#L57, shall we define a class for this?

(and clearly, this line is not hit by the CI as the issue was picked up by the linter only)
diff --git a/MANIFEST.in b/MANIFEST.in
index 4eacd66..25e0071 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,14 +1,13 @@
 include README.rst
 include CHANGES.rst
+include LICENSE.rst
 
 include setup.cfg
 include pyproject.toml
 
-recursive-include packagename *.pyx *.c *.pxd
+recursive-include pyvo *py
 recursive-include docs *
 recursive-include licenses *
-recursive-include cextern *
-recursive-include scripts *
 
 prune build
 prune docs/_build
diff --git a/pyvo/dal/adhoc.py b/pyvo/dal/adhoc.py
index 4079a13..6a2217c 100644
--- a/pyvo/dal/adhoc.py
+++ b/pyvo/dal/adhoc.py
@@ -107,6 +107,7 @@ class AdhocServiceResultsMixin:
     """
     Mixing for adhoc:service functionallity for results classes.
     """
+
     def __init__(self, votable, url=None, session=None):
         super().__init__(votable, url=url, session=session)
 
@@ -231,6 +232,7 @@ class DatalinkRecordMixin:
 
     - ``getdataset()`` considers datalink.
     """
+
     def getdatalink(self):
         try:
             datalink = self._results.get_adhocservice_by_ivoid(DATALINK_IVOID)
@@ -384,9 +386,9 @@ class DatalinkQuery(DALQuery):
             elif np.isscalar(input_param.value) and input_param.value:
                 query_params[name] = input_param.value
             elif (
-                    not np.isscalar(input_param.value) and
-                    input_param.value.all() and
-                    len(input_param.value)
+                    not np.isscalar(input_param.value)
+                    and input_param.value.all()
+                    and len(input_param.value)
             ):
                 query_params[name] = " ".join(
                     str(_) for _ in input_param.value)
@@ -562,9 +564,9 @@ class DatalinkResults(DatalinkResultsMixin, DALResults):
             for term in core_terms:
                 if term in voc["terms"]:
                     additional_terms.extend(voc["terms"][term]["narrower"])
-            core_terms = core_terms+additional_terms
+            core_terms = core_terms + additional_terms
 
-        semantics = set("#"+term for term in core_terms) | set(other_terms)
+        semantics = set("#" + term for term in core_terms) | set(other_terms)
         for record in self:
             if record.semantics in semantics:
                 yield record
@@ -636,6 +638,7 @@ class SodaRecordMixin:
     If used, it's result class must have
     `pyvo.dal.datalink.AdhocServiceResultsMixin` mixed in.
     """
+
     def _get_soda_resource(self):
         try:
             return self._results.get_adhocservice_by_ivoid(SODA_SYNC_IVOID)
@@ -856,6 +859,7 @@ class SodaQuery(DatalinkQuery, AxisParamMixin):
     """
     a class for preparing a query to a SODA Service.
     """
+
     def __init__(
             self, baseurl, circle=None, range=None, polygon=None, band=None,
             **kwargs):
diff --git a/pyvo/dal/dbapi2.py b/pyvo/dal/dbapi2.py
index 43e8018..8282999 100644
--- a/pyvo/dal/dbapi2.py
+++ b/pyvo/dal/dbapi2.py
@@ -91,7 +91,8 @@ class TypeObject:
         self._values = values
 
     @property
-    def id(self): return self._values[0]
+    def id(self):
+        return self._values[0]
 
     def __eq__(self, other):
         if not isinstance(other, TypeObject):
diff --git a/pyvo/dal/params.py b/pyvo/dal/params.py
index 8c085cd..dae3774 100644
--- a/pyvo/dal/params.py
+++ b/pyvo/dal/params.py
@@ -49,6 +49,7 @@ def unify_value(func):
     Decorator for serialize method to do unit conversion on input value.
     The decorator converts the input value to the unit in the input param.
     """
+
     def wrapper(self, value):
         if self._param.unit:
             value = Quantity(value)
@@ -80,6 +81,7 @@ class Converter:
     Base class for all converters. Each subclass handles the conversion of a
     input value based on a specific xtype.
     """
+
     def __init__(self, param):
         self._param = param
 
@@ -231,6 +233,7 @@ class AbstractDalQueryParam(MutableSet, metaclass=abc.ABCMeta):
     Duplicates in the set are determine based on the formatted DAL
     representation of the value.
     """
+
     def __init__(self, values=()):
         """
         Parameters
@@ -281,6 +284,7 @@ class StrQueryParam(AbstractDalQueryParam):
     Representation of a unitless, single-value parameter. The formatter is
     just a str() cast
     """
+
     def get_dal_format(self, val):
         return str(val)
 
@@ -290,6 +294,7 @@ class PosQueryParam(AbstractDalQueryParam):
     Representation of a position parameter. Depending on the number
     of entries, the resulting DAL format is CIRCLE, RANGE or POLYGON.
     """
+
     def get_dal_format(self, val):
         """
         formats the tuple values into a string to be sent to the service
@@ -308,7 +313,7 @@ class PosQueryParam(AbstractDalQueryParam):
                 'even 6 and above (POLYGON) accepted.'.format(val))
         return '{} {}'.format(shape, ' '.join(
             [str(val.to(u.deg).value) if isinstance(val, Quantity) else
-             str((val*u.deg).value) for val in val]))
+             str((val * u.deg).value) for val in val]))
 
     def _validate_pos(self, pos):
         """
@@ -323,7 +328,7 @@ class PosQueryParam(AbstractDalQueryParam):
                 radius = pos[2] * u.deg
             else:
                 radius = pos[2]
-            if radius <= 0*u.deg or radius.to(u.deg) > 90*u.deg:
+            if radius <= 0 * u.deg or radius.to(u.deg) > 90 * u.deg:
                 raise ValueError('Invalid circle radius: {}'.format(radius))
         elif len(pos) == 4:
             ra_min = pos[0] if isinstance(pos[0], Quantity) else pos[0] * u.deg
@@ -366,6 +371,7 @@ class IntervalQueryParam(AbstractDalQueryParam):
     """
     Representation of an interval DAL parameter.
     """
+
     def __init__(self, unit=None, equivalencies=None):
         """
         Parameters
@@ -397,10 +403,10 @@ class IntervalQueryParam(AbstractDalQueryParam):
                 low, high))
         if self._unit:
             if not isinstance(low, Quantity):
-                low = low*self._unit
+                low = low * self._unit
             low = low.to(self._unit, equivalencies=self._equivalencies).value
             if not isinstance(high, Quantity):
-                high = high*self._unit
+                high = high * self._unit
             high = high.to(self._unit, equivalencies=self._equivalencies).value
 
             if low > high:
@@ -414,6 +420,7 @@ class TimeQueryParam(AbstractDalQueryParam):
     """
     Representation of a timestamp parameter.
     """
+
     def get_dal_format(self, val):
         if isinstance(val, tuple):
             if len(val) == 1:
@@ -442,6 +449,7 @@ class EnumQueryParam(AbstractDalQueryParam):
     """
     Representation of an enum parameter
     """
+
     def __init__(self, allowed_values):
         """
         Parameters
diff --git a/pyvo/dal/query.py b/pyvo/dal/query.py
index fb68b1d..6ce8a5f 100644
--- a/pyvo/dal/query.py
+++ b/pyvo/dal/query.py
@@ -715,8 +715,8 @@ class Record(Mapping):
         for fieldname in self._results.fieldnames:
             field = self._results.getdesc(fieldname)
             if (field.utype and "access.reference" in field.utype.lower()) or (
-                    field.ucd and "meta.dataset" in field.ucd and
-                    "meta.ref.url" in field.ucd
+                    field.ucd and "meta.dataset" in field.ucd
+                    and "meta.ref.url" in field.ucd
             ):
                 out = self[fieldname]
                 if isinstance(out, bytes):
diff --git a/pyvo/dal/sia2.py b/pyvo/dal/sia2.py
index 9dc9f5e..a0a884c 100644
--- a/pyvo/dal/sia2.py
+++ b/pyvo/dal/sia2.py
@@ -169,9 +169,9 @@ class SIAService(DALService, AvailabilityMixin, CapabilityMixin):
             if cap.standardid.lower() == SIA2_STANDARD_ID.lower():
                 for interface in cap.interfaces:
                     if interface.accessurls and \
-                            not (len(interface.securitymethods) == 1 and
-                                 interface.securitymethods[0].standardid ==
-                                 'ivo://ivoa.net/sso#BasicAA'):
+                            not (len(interface.securitymethods) == 1
+                                 and interface.securitymethods[0].standardid
+                                 == 'ivo://ivoa.net/sso#BasicAA'):
                         self.query_ep = interface.accessurls[0].content
                         break
 
@@ -712,7 +712,7 @@ class ObsCoreRecord(SodaRecordMixin, DatalinkRecordMixin, Record,
         required. Provision of dataset size estimates is important whenever it
         is possible that datasets can be very large.
         """
-        return self.get('access_estsize')*1000*u.byte
+        return self.get('access_estsize') * 1000 * u.byte
 
     #           SPATIAL CHARACTERISATION
     @property
@@ -720,14 +720,14 @@ class ObsCoreRecord(SodaRecordMixin, DatalinkRecordMixin, Record,
         """
         ICRS Right Ascension of the center of the observation
         """
-        return self.get('s_ra')*u.deg
+        return self.get('s_ra') * u.deg
 
     @property
     def s_dec(self):
         """
         CRS Declination of the center of the observation
         """
-        return self.get('s_dec')*u.deg
+        return self.get('s_dec') * u.deg
 
     @property
     def s_fov(self):
@@ -744,7 +744,7 @@ class ObsCoreRecord(SodaRecordMixin, DatalinkRecordMixin, Record,
         data product. The spatial coverage of a data product can be more
         precisely specified using the region attribute.
         """
-        return self.get('s_fov')*u.deg
+        return self.get('s_fov') * u.deg
 
     @property
     def s_region(self):
@@ -773,7 +773,7 @@ class ObsCoreRecord(SodaRecordMixin, DatalinkRecordMixin, Record,
         characterisation may be necessary to fully specify the spatial
         characteristics of the data.
         """
-        return self.get('s_resolution')*u.arcsec
+        return self.get('s_resolution') * u.arcsec
 
     @property
     def s_xel1(self):
@@ -809,7 +809,7 @@ class ObsCoreRecord(SodaRecordMixin, DatalinkRecordMixin, Record,
         Resolution min value on spatial axis (FHWM of PSF)
         """
         rmin = self.get('s_resolution_min', default=None)
-        return rmin if not rmin else rmin*u.arcsec
+        return rmin if not rmin else rmin * u.arcsec
 
     @property
     def s_resolution_max(self):
@@ -898,14 +898,14 @@ class ObsCoreRecord(SodaRecordMixin, DatalinkRecordMixin, Record,
         often adjusted to achieve similar signal to noise ratio for different
         targets.
         """
-        return self.get('t_exptime')*u.second
+        return self.get('t_exptime') * u.second
 
     @property
     def t_resolution(self):
         """
         Estimated or average value of the temporal resolution.
         """
-        return self.get('t_resolution')*u.second
+        return self.get('t_resolution') * u.second
 
     @property
     def t_calib_status(self):
@@ -922,7 +922,7 @@ class ObsCoreRecord(SodaRecordMixin, DatalinkRecordMixin, Record,
         Time coord statistical error on the time measurements in seconds
         """
         ter = self.get('t_stat_error', default=None)
-        return ter if not ter else ter*u.second
+        return ter if not ter else ter * u.second
 
     #           SPECTRAL CHARACTERISATION
     @property
@@ -961,14 +961,14 @@ class ObsCoreRecord(SodaRecordMixin, DatalinkRecordMixin, Record,
         """
         Minimum of the spectral interval covered by the observation
         """
-        return self.get('em_min')*u.meter
+        return self.get('em_min') * u.meter
 
     @property
     def em_max(self):
         """
         Maximum of the spectral interval covered by the observation
         """
-        return self.get('em_max')*u.meter
+        return self.get('em_max') * u.meter
 
     @property
     def em_res_power(self):
@@ -1001,7 +1001,7 @@ class ObsCoreRecord(SodaRecordMixin, DatalinkRecordMixin, Record,
         power is preferable due to the LSF variation along the spectral axis.
         """
         if 'em_resolution' in self.keys():
-            return self.get('em_resolution')*u.meter
+            return self.get('em_resolution') * u.meter
         return None
 
     @property
@@ -1010,7 +1010,7 @@ class ObsCoreRecord(SodaRecordMixin, DatalinkRecordMixin, Record,
         Spectral coord statistical error (accuracy along the spectral axis)
         """
         if 'em_stat_error' in self.keys():
-            return self.get('em_stat_error')*u.meter
+            return self.get('em_stat_error') * u.meter
         return None
 
     #           OBSERVABLE AXIS
diff --git a/pyvo/dal/tests/test_adhoc.py b/pyvo/dal/tests/test_adhoc.py
index 7696d02..26a3f86 100644
--- a/pyvo/dal/tests/test_adhoc.py
+++ b/pyvo/dal/tests/test_adhoc.py
@@ -15,7 +15,7 @@ def test_pos():
     class TestClass(dict, AxisParamMixin):
         pass
     test_obj = TestClass()
-    test_obj.pos.add((1, 2, 3)*u.deg)
+    test_obj.pos.add((1, 2, 3) * u.deg)
     assert len(test_obj._pos) == 1
     assert test_obj['POS'] == ['CIRCLE 1.0 2.0 3.0']
 
@@ -41,9 +41,9 @@ def test_pos():
                                'POLYGON 1.0 2.0 3.0 4.0 5.0 6.0']
 
     # test borders
-    test_obj.pos.discard((1, 2, 3)*u.deg)
+    test_obj.pos.discard((1, 2, 3) * u.deg)
     test_obj.pos.discard((1, 2, 3, 4, 5, 6))
-    assert(len(test_obj._pos) == 0)
+    assert (len(test_obj._pos) == 0)
     test_obj.pos.add((0, 90, 90))
     assert len(test_obj._pos) == 1
     assert test_obj['POS'] == ['CIRCLE 0.0 90.0 90.0']
@@ -92,12 +92,12 @@ def test_band():
     test_obj.band.add(33)
     assert 33 in test_obj.band
     assert test_obj['BAND'] == ['33.0 33.0']
-    test_obj.band.add((50*u.meter, 500))
+    test_obj.band.add((50 * u.meter, 500))
     assert 33 in test_obj.band
-    assert (50*u.meter, 500) in test_obj.band
+    assert (50 * u.meter, 500) in test_obj.band
     assert test_obj['BAND'] == ['33.0 33.0', '50.0 500.0']
     test_obj.band.discard(33)
-    assert (50*u.meter, 500) in test_obj.band
+    assert (50 * u.meter, 500) in test_obj.band
     assert test_obj['BAND'] == ['50.0 500.0']
     test_obj.band.pop()
     assert not test_obj.band
@@ -198,7 +198,7 @@ def test_soda_query():
     assert not hasattr(test_obj, '_polygon')
     assert not hasattr(test_obj, '_range')
 
-    test_obj.range = (8, 9, 3, 4)*u.deg
+    test_obj.range = (8, 9, 3, 4) * u.deg
     assert test_obj['POS'] == 'RANGE 8.0 9.0 3.0 4.0'
     assert test_obj._range is not None
     assert not hasattr(test_obj, '_polygon')
diff --git a/pyvo/dal/tests/test_datalink.py b/pyvo/dal/tests/test_datalink.py
index 0d9b2d9..b7b869d 100644
--- a/pyvo/dal/tests/test_datalink.py
+++ b/pyvo/dal/tests/test_datalink.py
@@ -167,7 +167,7 @@ class TestSemanticsRetrieval:
     def test_access_without_expansion(self):
         datalink = DatalinkResults.from_result_url('http://example.com/proc')
         res = [r["access_url"] for r in datalink.bysemantics(
-                       ["#this", "#preview"], include_narrower=False)]
+            ["#this", "#preview"], include_narrower=False)]
         assert len(res) == 2
         assert res[0].endswith("eq010000ms/20100927.comb_avg.0001.fits.fz")
         assert res[1].endswith("http://dc.zah.uni-heidelberg.de/wider.dat")
@@ -183,10 +183,10 @@ class TestSemanticsRetrieval:
         datalink = DatalinkResults.from_result_url('http://example.com/proc')
         res = [r["access_url"]
                for r in datalink.bysemantics([
-                       "urn:example:rdf/dlext#oracle",
-                       'http://www.ivoa.net/rdf/datalink/core#preview',
-                       '#this',
-                       'non-existing-term'])]
+                   "urn:example:rdf/dlext#oracle",
+                   'http://www.ivoa.net/rdf/datalink/core#preview',
+                   '#this',
+                   'non-existing-term'])]
         assert len(res) == 4
         assert res[0].endswith("eq010000ms/20100927.comb_avg.0001.fits.fz")
         assert res[1].endswith("comb_avg.0001.fits.fz?preview=True")
diff --git a/pyvo/dal/tests/test_mimetype.py b/pyvo/dal/tests/test_mimetype.py
index 0ce26cc..345d6b2 100644
--- a/pyvo/dal/tests/test_mimetype.py
+++ b/pyvo/dal/tests/test_mimetype.py
@@ -18,7 +18,7 @@ get_pkg_data_contents = partial(
     get_pkg_data_contents, package=__package__, encoding='binary')
 
 try:
-    from PIL import Image
+    from PIL import Image  # noqa: F401
     HAS_PILLOW = True
 except ImportError:
     HAS_PILLOW = False
@@ -44,14 +44,14 @@ def mime(mocker):
 @pytest.mark.skipif('not HAS_PILLOW')
 def test_mime_object_maker():
 
-    assert 'Text content' == mime_object_maker(mime_url+'mime-text',
+    assert 'Text content' == mime_object_maker(mime_url + 'mime-text',
                                                'text/csv')
 
-    img = mime_object_maker(mime_url+'image', 'image/jpeg')
+    img = mime_object_maker(mime_url + 'image', 'image/jpeg')
     assert img
     assert 'JPEG' == img.format
 
-    fits = mime_object_maker(mime_url+'fits', 'application/fits')
+    fits = mime_object_maker(mime_url + 'fits', 'application/fits')
     assert 2 == len(fits)
 
     # error cases
diff --git a/pyvo/dal/tests/test_params.py b/pyvo/dal/tests/test_params.py
index 1abba9b..96853f3 100644
--- a/pyvo/dal/tests/test_params.py
+++ b/pyvo/dal/tests/test_params.py
@@ -179,7 +179,7 @@ def test_units():
     datalink = DatalinkResults.from_result_url('http://example.com/proc_units')
     proc = datalink[0]
 
-    proc.process(band=(6000*u.Angstrom, 80000*u.Angstrom))
+    proc.process(band=(6000 * u.Angstrom, 80000 * u.Angstrom))
 
 
 @pytest.mark.usefixtures('proc_inf')
@@ -216,12 +216,12 @@ def test_dal_format():
     iqp = IntervalQueryParam(unit=u.m, equivalencies=u.spectral())
     assert '1.0 1.0' == iqp.get_dal_format(1)
     assert '1.0 2.0' == iqp.get_dal_format((1, 2))
-    assert '1.0 2.0' == iqp.get_dal_format((100*u.cm, 200*u.cm))
-    assert '1.0 2.0' == iqp.get_dal_format((100, 200)*u.cm)
-    assert '0.14989622900000002 1.0' == iqp.get_dal_format((100*u.cm, 2*u.GHz))
-    assert '14.9896229 29.9792458' == iqp.get_dal_format((0.01, 0.02)*u.GHz)
+    assert '1.0 2.0' == iqp.get_dal_format((100 * u.cm, 200 * u.cm))
+    assert '1.0 2.0' == iqp.get_dal_format((100, 200) * u.cm)
+    assert '0.14989622900000002 1.0' == iqp.get_dal_format((100 * u.cm, 2 * u.GHz))
+    assert '14.9896229 29.9792458' == iqp.get_dal_format((0.01, 0.02) * u.GHz)
     # Quantity intervals are corrected in terms of min and max ..
-    assert '1.0 2.0' == iqp.get_dal_format((2, 1)*u.m)
+    assert '1.0 2.0' == iqp.get_dal_format((2, 1) * u.m)
     # But unitless intervals are not
     with pytest.raises(ValueError):
         iqp.get_dal_format((2, 1))
diff --git a/pyvo/dal/tests/test_sia2.py b/pyvo/dal/tests/test_sia2.py
index 498b628..2797972 100644
--- a/pyvo/dal/tests/test_sia2.py
+++ b/pyvo/dal/tests/test_sia2.py
@@ -50,7 +50,7 @@ def _test_result(record):
 @pytest.mark.filterwarnings("ignore::astropy.io.votable.exceptions.W06")
 def test_search():
     results = search('https://example.com/sia',
-                     pos=(33.3*u.deg, 4.2*u.deg, 0.0166*u.deg))
+                     pos=(33.3 * u.deg, 4.2 * u.deg, 0.0166 * u.deg))
     result = results[0]
 
     _test_result(result)
@@ -106,10 +106,10 @@ class TestSIAService:
         positions = [
             (2, 4, 0.0166 * u.deg),
             (12, 12.5, 34, 36),
-            (12.0*u.deg, 34.0*u.deg,
-             14.0*u.deg, 35.0*u.deg,
-             14.0*u.deg, 36.0*u.deg,
-             12.0*u.deg, 35.0*u.deg)]
+            (12.0 * u.deg, 34.0 * u.deg,
+             14.0 * u.deg, 35.0 * u.deg,
+             14.0 * u.deg, 36.0 * u.deg,
+             12.0 * u.deg, 35.0 * u.deg)]
 
         # each position
         for pos in positions:
@@ -129,10 +129,10 @@ class TestSIAQuery():
         query = SIAQuery('someurl')
         query.field_of_view.add((10, 20))
         assert query['FOV'] == ['10.0 20.0']
-        query.field_of_view.add((1*u.rad, 60))
+        query.field_of_view.add((1 * u.rad, 60))
         assert query['FOV'] == ['10.0 20.0', '57.29577951308232 60.0']
 
-        query.spatial_resolution.add((1*u.arcsec, 2))
+        query.spatial_resolution.add((1 * u.arcsec, 2))
         assert query['SPATRES'] == ['1.0 2.0']
 
         query.spectral_resolving_power.add((3, 5))
diff --git a/pyvo/dal/tests/test_sia2_remote.py b/pyvo/dal/tests/test_sia2_remote.py
index a99d1c3..f278004 100644
--- a/pyvo/dal/tests/test_sia2_remote.py
+++ b/pyvo/dal/tests/test_sia2_remote.py
@@ -161,7 +161,7 @@ class TestSIACadc():
         results = search(CADC_SIA_URL, spatial_resolution=(1, 2), maxrec=5)
         assert len(results) == 5
         for rr in results:
-            assert 1*u.arcsec <= rr.s_resolution <= 2*u.arcsec
+            assert 1 * u.arcsec <= rr.s_resolution <= 2 * u.arcsec
 
     @pytest.mark.filterwarnings("ignore::pyvo.dal.exceptions.DALOverflowWarning")
     def test_spec_resp(self):
@@ -176,7 +176,7 @@ class TestSIACadc():
                          maxrec=5)
         assert len(results) == 5
         for rr in results:
-            assert 1*u.second <= rr.t_exptime <= 2*u.second
+            assert 1 * u.second <= rr.t_exptime <= 2 * u.second
 
     @pytest.mark.filterwarnings("ignore::pyvo.dal.exceptions.DALOverflowWarning")
     def test_timeres(self):
@@ -238,4 +238,4 @@ class TestSIACadc():
         assert len(results) == 5
         for rr in results:
             assert rr.access_format == \
-                   'application/x-votable+xml;content=datalink'
+                'application/x-votable+xml;content=datalink'
diff --git a/pyvo/dal/tests/test_tap.py b/pyvo/dal/tests/test_tap.py
index 402a9f1..89f9e10 100644
--- a/pyvo/dal/tests/test_tap.py
+++ b/pyvo/dal/tests/test_tap.py
@@ -63,7 +63,7 @@ def create_fixture(mocker):
                 'Wrong file format'
         elif b'VOTable' in data:
             assert request.headers['Content-Type'] == \
-                   'application/x-votable+xml', 'Wrong file format'
+                'application/x-votable+xml', 'Wrong file format'
         else:
             assert False, 'BUG'
         return True
@@ -92,10 +92,10 @@ def load_fixture(mocker):
                 'Wrong file format'
         elif b'\t' in data:
             assert request.headers['Content-Type'] == \
-                   'text/tab-separated-values', 'Wrong file format'
+                'text/tab-separated-values', 'Wrong file format'
         elif b'FITSTable' in data:
             assert request.headers['Content-Type'] == \
-                   'application/fits', 'Wrong file format'
+                'application/fits', 'Wrong file format'
         else:
             assert False, 'BUG'
         return True
@@ -688,7 +688,7 @@ class TestTAPService:
                         headers={'Location': 'https://example.com/tap/uws'})
                 rm.get('https://example.com/tap/uws',
                        [{'content': get_index_job("PENDING")},
-                        {'content':get_index_job("COMPLETED")}])
+                        {'content': get_index_job("COMPLETED")}])
                 rm.post('https://example.com/tap/uws/phase', status_code=200)
                 # finally the call
                 service.create_index(table_name='abc', column_name='col1',
diff --git a/pyvo/io/vosi/exceptions.py b/pyvo/io/vosi/exceptions.py
index 297197d..dbe7a0e 100644
--- a/pyvo/io/vosi/exceptions.py
+++ b/pyvo/io/vosi/exceptions.py
@@ -188,8 +188,8 @@ class W15(VOSIWarning, XMLWarning):
     """
 
     message_template = (
-        'pyvo.dal is designed for VOSITables version 1.0, and 1.1, but ' +
-        'this file is {}')
+        'pyvo.dal is designed for VOSITables version 1.0, and 1.1, but '
+        + 'this file is {}')
     default_args = ('x',)
 
 
diff --git a/pyvo/io/vosi/tests/test_capabilities.py b/pyvo/io/vosi/tests/test_capabilities.py
index 2534766..16066b4 100644
--- a/pyvo/io/vosi/tests/test_capabilities.py
+++ b/pyvo/io/vosi/tests/test_capabilities.py
@@ -4,7 +4,6 @@
 Tests for pyvo.io.vosi
 """
 import io
-import logging
 from operator import eq as equals
 
 import pytest
@@ -20,7 +19,7 @@ from astropy.utils.data import get_pkg_data_filename
 @pytest.fixture()
 def parsed_caps():
     return vosi.parse_capabilities(get_pkg_data_filename(
-            "data/capabilities.xml"))
+        "data/capabilities.xml"))
 
 
 @pytest.mark.usefixtures("parsed_caps")
@@ -164,21 +163,21 @@ class TestInterface:
         assert len(parsed_caps[3].interfaces[0].mirrorurls) == 2
 
     def test_mirrors_have_titles(self, parsed_caps):
-        assert [m.title for m in parsed_caps[3].interfaces[0].mirrorurls
-            ] == ["https version", "Paris mirror"]
+        assert ([m.title for m in parsed_caps[3].interfaces[0].mirrorurls]
+                == ["https version", "Paris mirror"])
 
     def test_mirrors_have_urls(self, parsed_caps):
-        assert [m.content for m in parsed_caps[3].interfaces[0].mirrorurls
-            ] == ['https://example.org/tap', 'https://paris.example.org/tap']
+        assert ([m.content for m in parsed_caps[3].interfaces[0].mirrorurls]
+                == ['https://example.org/tap', 'https://paris.example.org/tap'])
 
     def test_testquerystring_parsed(self, parsed_caps):
         assert (parsed_caps[3].interfaces[0].testquerystring.content
-            == 'QUERY=SELECT%20*%20FROM%20tap_schema.tables&LANG=ADQL')
+                == 'QUERY=SELECT%20*%20FROM%20tap_schema.tables&LANG=ADQL')
 
 
 @pytest.fixture()
 def cap_with_free_prefix(recwarn):
-        caps = vosi.parse_capabilities(io.BytesIO(b"""
+    caps = vosi.parse_capabilities(io.BytesIO(b"""
 <ns2:capabilities xmlns:ns2="http://www.ivoa.net/xml/VOSICapabilities/v1.0">
   <capability
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
@@ -198,7 +197,7 @@ def cap_with_free_prefix(recwarn):
     </language>
   </capability>
 </ns2:capabilities>"""))
-        return recwarn, caps
+    return recwarn, caps
 
 
 # this is a test for when people ignore the canonical prefixes for
@@ -206,7 +205,7 @@ def cap_with_free_prefix(recwarn):
 class TestFreePrefixes:
     def test_parses_without_warning(self, cap_with_free_prefix):
         warnings, _ = cap_with_free_prefix
-        assert len(warnings)==0
+        assert len(warnings) == 0
 
     def test_parses_as_tapregext(self, cap_with_free_prefix):
         _, cap = cap_with_free_prefix
diff --git a/pyvo/io/vosi/tests/test_tables.py b/pyvo/io/vosi/tests/test_tables.py
index e8f4fd5..8b1c5df 100644
--- a/pyvo/io/vosi/tests/test_tables.py
+++ b/pyvo/io/vosi/tests/test_tables.py
@@ -376,8 +376,8 @@ class TestTables:
         """Test handling of describing tables with no description
         """
         tableset = vosi.parse_tables(
-                get_pkg_data_filename(
-                    "data/tables/no_table_description.xml"))
+            get_pkg_data_filename(
+                "data/tables/no_table_description.xml"))
         nodesc_table = tableset.get_first_table()
         assert nodesc_table.description is None
 
@@ -390,8 +390,8 @@ class TestTables:
         """Test describing a table with a single description
         """
         tableset = vosi.parse_tables(
-                get_pkg_data_filename(
-                    "data/tables/single_table_description.xml"))
+            get_pkg_data_filename(
+                "data/tables/single_table_description.xml"))
         onedesc_table = tableset.get_first_table()
         describe_string = 'A test table with a single description'
         assert describe_string in onedesc_table.description
diff --git a/pyvo/io/vosi/vodataservice.py b/pyvo/io/vosi/vodataservice.py
index 34e9899..a1c08d6 100644
--- a/pyvo/io/vosi/vodataservice.py
+++ b/pyvo/io/vosi/vodataservice.py
@@ -80,6 +80,7 @@ class TableSet(Element, HomogeneousList):
 
     The set of tables hosted by a resource.
     """
+
     def __init__(
         self, config=None, pos=None, _name='tableset', version='1.1', **kwargs
     ):
@@ -140,6 +141,7 @@ class TableSchema(Element, HomogeneousList):
 
     A detailed description of a logically-related set of tables.
     """
+
     def __init__(self, config=None, pos=None, _name='schema', **kwargs):
         HomogeneousList.__init__(self, Table)
         Element.__init__(self, config, pos, _name, **kwargs)
@@ -251,9 +253,10 @@ class ParamHTTP(vr.Interface):
     Note that the URL for help with this service can be put into
     the Service/ReferenceURL element.
     """
+
     def __init__(self, config=None, pos=None, _name='', **kwargs):
         super().__init__(
-                config=config, pos=pos, _name=_name, **kwargs)
+            config=config, pos=pos, _name=_name, **kwargs)
 
         self._querytypes = HomogeneousList(str)
         self._resulttype = None
@@ -290,6 +293,7 @@ class Table(Element):
     Table element as described in
     http://www.ivoa.net/xml/VODataService/v1.1
     """
+
     def __init__(
         self, config=None, pos=None, _name='table', version='1.1', **kwargs
     ):
@@ -455,9 +459,10 @@ class BaseParam(Element):
     normally employ a sub-class of this type (e.g. Param), rather than this
     type directly.
     """
+
     def __init__(self, config=None, pos=None, _name='', **kwargs):
         super().__init__(
-                config=config, pos=pos, _name=_name, **kwargs)
+            config=config, pos=pos, _name=_name, **kwargs)
 
         self._name = None
         self._description = None
@@ -561,7 +566,7 @@ class TableParam(BaseParam):
 
     def __init__(self, config=None, pos=None, _name='', std=None, **kwargs):
         super().__init__(
-                config=config, pos=pos, _name=_name, **kwargs)
+            config=config, pos=pos, _name=_name, **kwargs)
 
         self._datatype = None
         self._flags = HomogeneousList(str)
@@ -627,6 +632,7 @@ class InputParam(BaseParam):
 
     A description of a service or function parameter having a fixed data type.
     """
+
     def __init__(
             self, config=None, pos=None, _name='', use="optional", std="1",
             **kwargs):
@@ -693,6 +699,7 @@ class DataType(ContentMixin, ElementWithXSIType):
     This XML type is used as a parent for defining data types with a restricted
     set of names.
     """
+
     def __init__(
             self, config=None, pos=None, _name='dataType',
             arraysize=None, delim=None, extendedType=None, extendedSchema=None,
@@ -799,6 +806,7 @@ class SimpleDataType(DataType):
     This set is intended for describing simple input parameters to a service or
     function.
     """
+
     def _content_check(self, value):
         if value is not None:
             valid_values = {
@@ -826,6 +834,7 @@ class VOTableType(TableDataType):
     VOTableType element as described in
     http://www.ivoa.net/xml/VODataService/v1.1
     """
+
     def _content_check(self, value):
         if value is not None:
             valid_values = (
@@ -844,6 +853,7 @@ class TAPDataType(TableDataType):
     an abstract parent for the specific data types supported by the
     Table Access Protocol.
     """
+
     def __init__(
         self, config=None, pos=None, _name='dataType', size=None, **kwargs
     ):
@@ -880,6 +890,7 @@ class TAPType(TAPDataType):
 
     a data type supported explicitly by the Table Access Protocol (v1.0).
     """
+
     def _content_check(self, value):
         if value is not None:
             valid_values = (
@@ -895,9 +906,10 @@ class FKColumn(Element):
     FKColumn element as described in
     http://www.ivoa.net/xml/VODataService/v1.1
     """
+
     def __init__(self, config=None, pos=None, _name='fkColumn', **kwargs):
         super().__init__(
-                config=config, pos=pos, _name=_name, **kwargs)
+            config=config, pos=pos, _name=_name, **kwargs)
 
         self._fromcolumn = None
         self._targetcolumn = None
@@ -942,6 +954,7 @@ class ForeignKey(Element):
     ForeignKey element as described in
     http://www.ivoa.net/xml/VODataService/v1.1
     """
+
     def __init__(self, config=None, pos=None, _name='foreignKey', **kwargs):
         Element.__init__(self, config, pos, _name, **kwargs)
 
diff --git a/pyvo/registry/regtap.py b/pyvo/registry/regtap.py
index 93de16b..fbb6776 100644
--- a/pyvo/registry/regtap.py
+++ b/pyvo/registry/regtap.py
@@ -30,10 +30,10 @@ from ..utils.formatting import para_format_desc
 
 
 __all__ = ["search", "get_RegTAP_query",
-    "RegistryResource", "RegistryResults", "ivoid2service"]
+           "RegistryResource", "RegistryResults", "ivoid2service"]
 
 REGISTRY_BASEURL = os.environ.get("IVOA_REGISTRY", "http://reg.g-vo.org/tap"
-    ).rstrip("/")
+                                  ).rstrip("/")
 
 
 # ADQL only has string_agg, where we need string arrays.  We fake arrays
@@ -65,7 +65,7 @@ def expand_stdid(s):
     """
     if s is None or "://" in s:
         return s
-    return "ivo://ivoa.net/std/"+s
+    return "ivo://ivoa.net/std/" + s
 
 
 @functools.lru_cache(1)
@@ -80,15 +80,15 @@ def get_RegTAP_service():
     return tap.TAPService(REGISTRY_BASEURL)
 
 
-def get_RegTAP_query(*constraints:rtcons.Constraint,
-        includeaux=False, **kwargs):
+def get_RegTAP_query(*constraints: rtcons.Constraint,
+                     includeaux=False, **kwargs):
     """returns SQL for a RegTAP query for constraints and keywords.
 
     This function's parameters are as for search; this is basically
     a wrapper for rtcons.build_regtap_query maintaining the legacy
     keyword-based interface.
     """
-    constraints = list(constraints)+rtcons.keywords_to_constraints(kwargs)
+    constraints = list(constraints) + rtcons.keywords_to_constraints(kwargs)
 
     # maintain legacy includeaux by locating any Servicetype constraints
     # and replacing them with ones that includes auxiliaries.
@@ -100,10 +100,8 @@ def get_RegTAP_query(*constraints:rtcons.Constraint,
     return rtcons.build_regtap_query(constraints)
 
 
-def search(*constraints:rtcons.Constraint,
-        includeaux:bool=False,
-        maxrec:int=None,
-        **kwargs):
+def search(*constraints: rtcons.Constraint, includeaux: bool = False, maxrec: int = None, **kwargs):
+
     """
     execute a simple query to the RegTAP registry.
 
@@ -189,6 +187,7 @@ class RegistryResults(dalq.DALResults):
     matters, you need to use full ivoids as index.
 
     """
+
     def getrecord(self, index):
         """
         return all the attributes of a resource record with the given index
@@ -209,11 +208,11 @@ class RegistryResults(dalq.DALResults):
         like to inspect the matches in, perhaps, notebooks.
         """
         return table.Table([
-                list(range(len(self))),
-                [r.short_name for r in self],
-                [r.res_title for r in self],
-                [r.res_description for r in self],
-                [", ".join(sorted(r.access_modes())) for r in self]],
+            list(range(len(self))),
+            [r.short_name for r in self],
+            [r.res_title for r in self],
+            [r.res_description for r in self],
+            [", ".join(sorted(r.access_modes())) for r in self]],
             names=("index", "short_name", "title", "description", "interfaces"),
             descriptions=(
                 "Index to access the resource within self",
@@ -225,12 +224,12 @@ class RegistryResults(dalq.DALResults):
     @functools.lru_cache(maxsize=None)
     def _get_ivo_index(self):
         return dict((r.ivoid, index)
-            for index, r in enumerate(self))
+                    for index, r in enumerate(self))
 
     @functools.lru_cache(maxsize=None)
     def _get_short_name_index(self):
         return dict((r.short_name, index)
-            for index, r in enumerate(self))
+                    for index, r in enumerate(self))
 
     def __getitem__(self, item):
         """
@@ -256,6 +255,7 @@ class _BrowserService:
     """A pseudo-service class just opening a web browser for browser-based
     services.
     """
+
     def __init__(self, access_url):
         self.access_url = access_url
 
@@ -281,11 +281,11 @@ class Interface:
     as in regtap (e.g., lowercased for the standardIDs).
     """
     service_for_standardid = {
-           "ivo://ivoa.net/std/conesearch":  scs.SCSService,
-           "ivo://ivoa.net/std/sia":  sia.SIAService,
-           "ivo://ivoa.net/std/ssa":  ssa.SSAService,
-           "ivo://ivoa.net/std/sla":  sla.SLAService,
-           "ivo://ivoa.net/std/tap":  tap.TAPService}
+        "ivo://ivoa.net/std/conesearch": scs.SCSService,
+        "ivo://ivoa.net/std/sia": sia.SIAService,
+        "ivo://ivoa.net/std/ssa": ssa.SSAService,
+        "ivo://ivoa.net/std/sla": sla.SLAService,
+        "ivo://ivoa.net/std/tap": tap.TAPService}
 
     def __init__(self, access_url, standard_id, intf_type, intf_role):
         self.access_url = access_url
@@ -293,25 +293,25 @@ class Interface:
         self.is_vosi = standard_id.startswith("ivo://ivoa.net/std/vosi")
         self.type = intf_type or None
         self.role = intf_role or None
-        self.is_standard = self.role=="std"
+        self.is_standard = self.role == "std"
 
     def __repr__(self):
         return (f"Interface({self.access_url!r}, {self.standard_id!r},"
-            f" {self.type!r}, {self.role!r})")
+                f" {self.type!r}, {self.role!r})")
 
     def to_service(self):
-        if self.type=="vr:webbrowser":
+        if self.type == "vr:webbrowser":
             return _BrowserService(self.access_url)
 
         if self.standard_id is None or not self.is_standard:
             raise ValueError("This is not a standard interface.  PyVO"
-                " cannot speak to it.")
+                             " cannot speak to it.")
 
         service_class = self.service_for_standardid.get(
             self.standard_id.split("#")[0])
         if service_class is None:
             raise ValueError("PyVO has no support for interfaces with"
-                f" standard id {self.standard_id}.")
+                             f" standard id {self.standard_id}.")
 
         return service_class(self.access_url)
 
@@ -334,7 +334,7 @@ class Interface:
         """
         if not self.standard_id:
             return False
-        return self.standard_id.split("#")[0]==standard_id.split("#")[0]
+        return self.standard_id.split("#")[0] == standard_id.split("#")[0]
 
 
 class RegistryResource(dalq.Record):
@@ -379,26 +379,26 @@ class RegistryResource(dalq.Record):
         (f"\n  ivo_string_agg(COALESCE(intf_type, ''), '{TOKEN_SEP}')",
             "intf_types"),
         (f"\n  ivo_string_agg(COALESCE(intf_role, ''), '{TOKEN_SEP}')",
-            "intf_roles"),]
+            "intf_roles"), ]
 
     def __init__(self, results, index, session=None):
         dalq.Record.__init__(self, results, index, session)
 
         self._mapping["access_urls"
-            ] = self._parse_pseudo_array(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._parse_pseudo_array(self._mapping["standard_ids"])
         self._mapping["intf_types"
-            ] = self._parse_pseudo_array(self._mapping["intf_types"])
+                      ] = self._parse_pseudo_array(self._mapping["intf_types"])
         self._mapping["intf_roles"
-            ] = self._parse_pseudo_array(self._mapping["intf_roles"])
+                      ] = self._parse_pseudo_array(self._mapping["intf_roles"])
 
         self.interfaces = [Interface(*props)
-            for props in zip(
-                self["access_urls"],
-                self["standard_ids"],
-                self["intf_types"],
-                self["intf_roles"])]
+                           for props in zip(
+            self["access_urls"],
+            self["standard_ids"],
+            self["intf_types"],
+            self["intf_roles"])]
 
     @staticmethod
     def _parse_pseudo_array(literal):
@@ -530,11 +530,11 @@ class RegistryResource(dalq.Record):
         # multiple times in here.  Be cool about that situation:
         access_urls = list(sorted(set(self["access_urls"])))
 
-        if len(access_urls)==0:
+        if len(access_urls) == 0:
             raise dalq.DALQueryError(
                 f"The resource {self.ivoid} has no queriable interfaces.")
 
-        elif len(access_urls)>1:
+        elif len(access_urls) > 1:
             warnings.warn(AstropyDeprecationWarning(
                 f"The resource {self.ivoid} has multiple capabilities. "
                 " You should explicitly pick one using get_service. "
@@ -548,7 +548,7 @@ class RegistryResource(dalq.Record):
         the IVOA standard identifier
         """
         standard_ids = list(set(self["standard_ids"]))
-        if len(standard_ids)==1:
+        if len(standard_ids) == 1:
             return standard_ids[0]
         else:
             raise dalq.DALQueryError(
@@ -568,14 +568,14 @@ class RegistryResource(dalq.Record):
         This will ignore VOSI (infrastructure) services.
         """
         return set(shorten_stdid(intf.standard_id) or "web"
-            for intf in self.interfaces
-            if (intf.standard_id or intf.type=="vr:webbrowser")
-                and not intf.is_vosi)
+                   for intf in self.interfaces
+                   if (intf.standard_id or intf.type == "vr:webbrowser")
+                   and not intf.is_vosi)
 
     def get_interface(self,
-            service_type:str,
-            lax:bool=True,
-            std_only:bool=False):
+                      service_type: str,
+                      lax: bool = True,
+                      std_only: bool = False):
         """returns a regtap.Interface class for service_type.
 
         Parameters
@@ -591,11 +591,11 @@ class RegistryResource(dalq.Record):
             want when you want to construct pyVO service objects later.
             This parameter is ignored for the "web" service type.
         """
-        if service_type=="web":
+        if service_type == "web":
             # this works very much differently in the Registry
             # than do the proper services
             candidates = [intf for intf in self.interfaces
-                if intf.type=="vr:webbrowser"]
+                          if intf.type == "vr:webbrowser"]
 
         else:
             service_type = expand_stdid(
@@ -603,23 +603,23 @@ class RegistryResource(dalq.Record):
                     service_type, service_type))
 
             candidates = [intf for intf in self.interfaces
-                if ((not std_only) or intf.is_standard)
-                    and not intf.is_vosi
-                    and ((not service_type) or intf.supports(service_type))]
+                          if ((not std_only) or intf.is_standard)
+                          and not intf.is_vosi
+                          and ((not service_type) or intf.supports(service_type))]
 
         if not candidates:
             raise ValueError(
                 "No matching interface.")
-        if len(candidates)>1 and not lax:
+        if len(candidates) > 1 and not lax:
             raise ValueError("Multiple matching interfaces found."
-                "  Perhaps pass in service_type or use a Servicetype"
-                " constrain in the registry.search?  Or use lax=True?")
+                             "  Perhaps pass in service_type or use a Servicetype"
+                             " constrain in the registry.search?  Or use lax=True?")
 
         return candidates[0]
 
     def get_service(self,
-            service_type:str=None,
-            lax:bool=True):
+                    service_type: str = None,
+                    lax: bool = True):
         """
         return an appropriate DALService subclass for this resource that
         can be used to search the resource using service_type.
@@ -664,7 +664,7 @@ class RegistryResource(dalq.Record):
             opening a web browser on the access URL.
         """
         return self.get_interface(service_type, lax, std_only=True
-            ).to_service()
+                                  ).to_service()
 
     @property
     def service(self):
@@ -736,9 +736,9 @@ class RegistryResource(dalq.Record):
         print("Short Name: " + self.short_name, file=file)
         print("IVOA Identifier: " + self.ivoid, file=file)
         print("Access modes: " + ", ".join(sorted(self.access_modes())),
-            file=file)
+              file=file)
 
-        if len(self._mapping["access_urls"])==1:
+        if len(self._mapping["access_urls"]) == 1:
             print("Base URL: " + self.access_url, file=file)
         else:
             print("Multi-capabilty service -- use get_service()", file=file)
@@ -774,7 +774,7 @@ class RegistryResource(dalq.Record):
             WHERE
                 base_role='contact'
                 AND ivoid={}""".format(
-                    rtcons.make_sql_literal(self.ivoid)))
+            rtcons.make_sql_literal(self.ivoid)))
 
         contacts = []
         for row in res:
@@ -845,11 +845,11 @@ class RegistryResource(dalq.Record):
             """SELECT table_name, table_description, table_index, table_title
             FROM rr.res_table
             WHERE ivoid={}""".format(
-                    rtcons.make_sql_literal(self.ivoid)))
-        if len(tables)>table_limit:
+                rtcons.make_sql_literal(self.ivoid)))
+        if len(tables) > table_limit:
             raise dalq.DALQueryError(f"Resource {self.ivoid} reports"
-                f" {len(tables)} tables.  Pass a higher table_limit"
-                " to see them all.")
+                                     f" {len(tables)} tables.  Pass a higher table_limit"
+                                     " to see them all.")
 
         res = {}
         for table_row in tables:
@@ -881,10 +881,10 @@ def ivoid2service(ivoid, servicetype=None):
     if servicetype is not None:
         constraints.append(rtcons.Servicetype(servicetype))
     resources = search(*constraints)
-    if len(resources)==0:
+    if len(resources) == 0:
         if servicetype:
             raise dalq.DALQueryError(f"No resource {ivoid} with"
-                f" {servicetype} capability.")
+                                     f" {servicetype} capability.")
         else:
             raise dalq.DALQueryError(f"No resource {ivoid}")
 
diff --git a/pyvo/registry/rtcons.py b/pyvo/registry/rtcons.py
index 1c1e678..2d86e6a 100644
--- a/pyvo/registry/rtcons.py
+++ b/pyvo/registry/rtcons.py
@@ -17,34 +17,33 @@ from astropy import constants
 from astropy.coordinates import SkyCoord
 import numpy
 
-from ..dal import tap
 from ..dal import query as dalq
 from ..utils import vocabularies
 from .import regtap
 
 
 __all__ = ["Freetext", "Author", "Servicetype", "Waveband",
-    "Datamodel", "Ivoid", "UCD", "Spatial", "Spectral", "Temporal",
-    "build_regtap_query"]
+           "Datamodel", "Ivoid", "UCD", "Spatial", "Spectral", "Temporal",
+           "build_regtap_query"]
 
 
 # a mapping of service type shorthands to the ivoids of the
 # corresponding standards.  This is mostly to keep legacy APIs.
 # In the future, preferably rely on shorten_stdid and expand_stdid
 # from regtap.
-SERVICE_TYPE_MAP = dict((k, "ivo://ivoa.net/std/"+v)
-    for k, v in [
-        ("image", "sia"),
-        ("sia", "sia"),
-        ("spectrum", "ssa"),
-        ("ssap", "ssa"),
-        ("ssa", "ssa"),
-        ("scs", "conesearch"),
-        ("conesearch", "conesearch"),
-        ("line", "slap"),
-        ("slap", "slap"),
-        ("table", "tap"),
-        ("tap", "tap"),
+SERVICE_TYPE_MAP = dict((k, "ivo://ivoa.net/std/" + v)
+                        for k, v in [
+    ("image", "sia"),
+    ("sia", "sia"),
+    ("spectrum", "ssa"),
+    ("ssap", "ssa"),
+    ("ssa", "ssa"),
+    ("scs", "conesearch"),
+    ("conesearch", "conesearch"),
+    ("line", "slap"),
+    ("slap", "slap"),
+    ("table", "tap"),
+    ("tap", "tap"),
 ])
 
 
@@ -96,7 +95,7 @@ def make_sql_literal(value):
 
     else:
         raise ValueError("Cannot format {} as a SQL literal"
-            .format(repr(value)))
+                         .format(repr(value)))
 
 
 def format_function_call(func_name, args):
@@ -166,7 +165,7 @@ class Constraint:
         """
         if self._condition is None:
             raise NotImplementedError("{} is an abstract Constraint"
-                .format(self.__class__.__name__))
+                                      .format(self.__class__.__name__))
 
         return self._condition.format(**self._get_sql_literals())
 
@@ -187,7 +186,7 @@ class Freetext(Constraint):
     """
     _keyword = "keywords"
 
-    def __init__(self, *words:str):
+    def __init__(self, *words: str):
         """
 
         Parameters
@@ -205,18 +204,18 @@ class Freetext(Constraint):
         # faster than direct ORs.
         base_queries = [
             "SELECT ivoid FROM rr.resource WHERE"
-                " 1=ivo_hasword(res_description, {{{parname}}})",
+            " 1=ivo_hasword(res_description, {{{parname}}})",
             "SELECT ivoid FROM rr.resource WHERE"
-                " 1=ivo_hasword(res_title, {{{parname}}})",
+            " 1=ivo_hasword(res_title, {{{parname}}})",
             "SELECT ivoid FROM rr.res_subject WHERE"
-                " res_subject ILIKE {{{parpatname}}}"]
+            " res_subject ILIKE {{{parpatname}}}"]
         self._fillers, subqueries = {}, []
 
         for index, word in enumerate(words):
             parname = "fulltext{}".format(index)
             parpatname = "fulltextpar{}".format(index)
             self._fillers[parname] = word
-            self._fillers[parpatname] = '%'+word+'%'
+            self._fillers[parpatname] = '%' + word + '%'
             for q in base_queries:
                 subqueries.append(q.format(**locals()))
 
@@ -233,7 +232,7 @@ class Author(Constraint):
     """
     _keyword = "author"
 
-    def __init__(self, name:str):
+    def __init__(self, name: str):
         """
 
         Parameters
@@ -301,8 +300,8 @@ class Servicetype(Constraint):
                 self.stdids.add(std)
             else:
                 raise dalq.DALQueryError("Service type {} is neither a full"
-                    " standard URI nor one of the bespoke identifiers"
-                    " {}".format(std, ", ".join(SERVICE_TYPE_MAP)))
+                                         " standard URI nor one of the bespoke identifiers"
+                                         " {}".format(std, ", ".join(SERVICE_TYPE_MAP)))
 
     def get_search_condition(self):
         # we sort the stdids to make it easy for tests (and it's
@@ -317,7 +316,7 @@ class Servicetype(Constraint):
         This is a convenience to maintain registry.search's signature.
         """
         return Servicetype(*(self.stdids | set(
-            std+'#aux' for std in self.stdids)))
+            std + '#aux' for std in self.stdids)))
 
 
 class Waveband(Constraint):
@@ -348,7 +347,7 @@ class Waveband(Constraint):
         """
         if self.__class__._legal_terms is None:
             self.__class__._legal_terms = {w.lower() for w in
-                vocabularies.get_vocabulary("messenger")["terms"]}
+                                           vocabularies.get_vocabulary("messenger")["terms"]}
 
         bands = [band.lower() for band in bands]
         for band in bands:
@@ -398,7 +397,7 @@ class Datamodel(Constraint):
         dmname = dmname.lower()
         if dmname not in self._known_dms:
             raise dalq.DALQueryError("Unknown data model id {}.  Known are: {}."
-                .format(dmname, ", ".join(sorted(self._known_dms))))
+                                     .format(dmname, ", ".join(sorted(self._known_dms))))
         self._condition = getattr(self, f"_make_{dmname}_constraint")()
 
     def _make_obscore_constraint(self):
@@ -407,7 +406,7 @@ class Datamodel(Constraint):
         self._extra_tables = ["rr.res_detail"]
         obscore_pat = 'ivo://ivoa.net/std/obscore%'
         return ("detail_xpath = '/capability/dataModel/@ivo-id'"
-            f" AND 1 = ivo_nocasematch(detail_value, '{obscore_pat}')")
+                f" AND 1 = ivo_nocasematch(detail_value, '{obscore_pat}')")
 
     def _make_epntap_constraint(self):
         self._extra_tables = ["rr.res_table"]
@@ -415,14 +414,14 @@ class Datamodel(Constraint):
         # any new identifiers (utypes case-fold).
         return " OR ".join(
             f"table_utype LIKE {pat}'" for pat in
-                ['ivo://vopdc.obspm/std/epncore#schema-2.%',
-                    'ivo://ivoa.net/std/epntap#table-2.%'])
+            ['ivo://vopdc.obspm/std/epncore#schema-2.%',
+             'ivo://ivoa.net/std/epntap#table-2.%'])
 
     def _make_regtap_constraint(self):
         self._extra_tables = ["rr.res_detail"]
         regtap_pat = 'ivo://ivoa.net/std/RegTAP#1.%'
         return ("detail_xpath = '/capability/dataModel/@ivo-id'"
-            f" AND 1 = ivo_nocasematch(detail_value, '{regtap_pat}')")
+                f" AND 1 = ivo_nocasematch(detail_value, '{regtap_pat}')")
 
 
 class Ivoid(Constraint):
@@ -468,7 +467,7 @@ class UCD(Constraint):
         self._condition = " OR ".join(
             f"ucd LIKE {{ucd{i}}}" for i in range(len(patterns)))
         self._fillers = dict((f"ucd{index}", pattern)
-            for index, pattern in enumerate(patterns))
+                             for index, pattern in enumerate(patterns))
 
 
 class Spatial(Constraint):
@@ -546,20 +545,20 @@ class Spatial(Constraint):
 
         elif isinstance(geom_spec, SkyCoord):
             geom = tomoc(format_function_call("POINT",
-                (geom_spec.ra.value, geom_spec.dec.value)))
+                                              (geom_spec.ra.value, geom_spec.dec.value)))
 
-        elif len(geom_spec)==2:
+        elif len(geom_spec) == 2:
             if isinstance(geom_spec[0], SkyCoord):
                 geom = tomoc(format_function_call("CIRCLE",
-                    [geom_spec[0].ra.value, geom_spec[0].dec.value,
-                    geom_spec[1]]))
+                                                  [geom_spec[0].ra.value, geom_spec[0].dec.value,
+                                                   geom_spec[1]]))
             else:
                 geom = tomoc(format_function_call("POINT", geom_spec))
 
-        elif len(geom_spec)==3:
+        elif len(geom_spec) == 3:
             geom = tomoc(format_function_call("CIRCLE", geom_spec))
 
-        elif len(geom_spec)%2==0:
+        elif len(geom_spec) % 2 == 0:
             geom = tomoc(format_function_call("POLYGON", geom_spec))
 
         else:
@@ -621,7 +620,7 @@ class Spectral(Constraint):
                 "spec_lo": self._to_joule(spec[0]),
                 "spec_hi": self._to_joule(spec[1])}
             self._condition = ("1 = ivo_interval_overlaps("
-                "spectral_start, spectral_end, {spec_lo}, {spec_hi})")
+                               "spectral_start, spectral_end, {spec_lo}, {spec_hi})")
 
         else:
             self._fillers = {
@@ -640,19 +639,19 @@ class Spectral(Constraint):
             # is it an energy?
             return quant.to(units.Joule).value
         except units.UnitConversionError:
-            pass # try next
+            pass  # try next
 
         try:
             # is it a wavelength?
-            return (constants.h*constants.c/quant.to(units.m)).value
+            return (constants.h * constants.c / quant.to(units.m)).value
         except units.UnitConversionError:
-            pass # try next
+            pass  # try next
 
         try:
             # is it a frequency?
-            return (constants.h*quant.to(units.Hz)).value
+            return (constants.h * quant.to(units.Hz)).value
         except units.UnitConversionError:
-            pass # fall through to give up
+            pass  # fall through to give up
 
         raise ValueError(f"Cannot make a spectral quantity out of {quant}")
 
@@ -705,7 +704,7 @@ class Temporal(Constraint):
                 "time_lo": self._to_mjd(times[0]),
                 "time_hi": self._to_mjd(times[1])}
             self._condition = ("1 = ivo_interval_overlaps("
-                "time_start, time_end, {time_lo}, {time_hi})")
+                               "time_start, time_end, {time_lo}, {time_hi})")
 
         else:
             self._fillers = {
@@ -725,7 +724,7 @@ class Temporal(Constraint):
         val = quant.to_value('mjd')
         if not isinstance(val, numpy.number):
             raise ValueError("RegTAP time constraints must be made from"
-                " single time instants.")
+                             " single time instants.")
         return val
 
 
@@ -758,11 +757,11 @@ def build_regtap_query(constraints):
         if isinstance(constraint, str):
             constraint = Freetext(constraint)
 
-        serialized.append("("+constraint.get_search_condition()+")")
+        serialized.append("(" + constraint.get_search_condition() + ")")
         extra_tables |= set(constraint._extra_tables)
 
     joined_tables = ["rr.resource", "rr.capability", "rr.interface"
-        ]+list(extra_tables)
+                     ] + list(extra_tables)
 
     # see comment in regtap.RegistryResource for the following
     # oddity
@@ -775,13 +774,13 @@ def build_regtap_query(constraints):
             select_clause.append("{} AS {}".format(*col_desc))
 
     fragments = ["SELECT",
-        ", ".join(select_clause),
-        "FROM",
-        "\nNATURAL LEFT OUTER JOIN ".join(joined_tables),
-        "WHERE",
-        "\n  AND ".join(serialized),
-        "GROUP BY",
-        ", ".join(plain_columns)]
+                 ", ".join(select_clause),
+                 "FROM",
+                 "\nNATURAL LEFT OUTER JOIN ".join(joined_tables),
+                 "WHERE",
+                 "\n  AND ".join(serialized),
+                 "GROUP BY",
+                 ", ".join(plain_columns)]
 
     return "\n".join(fragments)
 
@@ -807,8 +806,8 @@ def keywords_to_constraints(keywords):
     for keyword, value in keywords.items():
         if keyword not in _KEYWORD_TO_CONSTRAINT:
             raise TypeError(f"{keyword} is not a valid registry"
-                " constraint keyword.  Use one of {}.".format(
-                    ", ".join(sorted(_KEYWORD_TO_CONSTRAINT))))
+                            " constraint keyword.  Use one of {}.".format(
+                                ", ".join(sorted(_KEYWORD_TO_CONSTRAINT))))
 
         constraint_class = _KEYWORD_TO_CONSTRAINT[keyword]
         if (isinstance(value, (tuple, list))
diff --git a/pyvo/registry/tests/commonfixtures.py b/pyvo/registry/tests/commonfixtures.py
index 15dfcef..532bebb 100644
--- a/pyvo/registry/tests/commonfixtures.py
+++ b/pyvo/registry/tests/commonfixtures.py
@@ -3,8 +3,6 @@
 Common fixtures for pyVO registry tests
 """
 
-import os
-
 import pytest
 
 from astropy.utils.data import (
@@ -12,7 +10,7 @@ from astropy.utils.data import (
     import_file_to_cache)
 # We need to populate the vocabulary cache with our test data;
 # we cannot use requests_mock here because a.u.data uses urllib.
-from astropy.utils.data import _get_download_cache_loc, _url_to_dirname
+from astropy.utils.data import _get_download_cache_loc, _url_to_dirname  # noqa: F401
 
 
 @pytest.fixture()
diff --git a/pyvo/registry/tests/test_regtap.py b/pyvo/registry/tests/test_regtap.py
index 59abd25..98c07a4 100644
--- a/pyvo/registry/tests/test_regtap.py
+++ b/pyvo/registry/tests/test_regtap.py
@@ -34,7 +34,7 @@ def capabilities(mocker):
         return get_pkg_data_contents('data/capabilities.xml')
 
     with mocker.register_uri(
-        'GET', REGISTRY_BASEURL+'/capabilities', content=callback
+        'GET', REGISTRY_BASEURL + '/capabilities', content=callback
     ) as matcher:
         yield matcher
 
@@ -46,15 +46,14 @@ def capabilities(mocker):
 # with open("data/regtap.xml", "wb") as f:
 # 	f.write(requests.get(regtap.REGISTRY_BASEURL+"/sync", {
 # 		"LANG": "ADQL",
-# 		"QUERY": regtap.get_RegTAP_query(
-#			keywords="pulsar", ucd=["pos.distance"])}).content)
+# 		"QUERY": regtap.get_RegTAP_query(keywords="pulsar", ucd=["pos.distance"])}).content)
 
 
 @pytest.fixture()
 def regtap_pulsar_distance_response(mocker):
     with mocker.register_uri(
-        'POST', REGISTRY_BASEURL+'/sync',
-        content=get_pkg_data_contents('data/regtap.xml')) as matcher:
+        'POST', REGISTRY_BASEURL + '/sync',
+            content=get_pkg_data_contents('data/regtap.xml')) as matcher:
         yield matcher
 
 
@@ -75,7 +74,7 @@ def keywords_fixture(mocker):
         return get_pkg_data_contents('data/regtap.xml')
 
     with mocker.register_uri(
-        'POST', REGISTRY_BASEURL+'/sync',
+        'POST', REGISTRY_BASEURL + '/sync',
         content=keywordstest_callback
     ) as matcher:
         yield matcher
@@ -94,7 +93,7 @@ def single_keyword_fixture(mocker):
         return get_pkg_data_contents('data/regtap.xml')
 
     with mocker.register_uri(
-        'POST', REGISTRY_BASEURL+'/sync',
+        'POST', REGISTRY_BASEURL + '/sync',
         content=keywordstest_callback
     ) as matcher:
         yield matcher
@@ -115,7 +114,7 @@ def servicetype_fixture(mocker):
         return get_pkg_data_contents('data/regtap.xml')
 
     with mocker.register_uri(
-        'POST', REGISTRY_BASEURL+'/sync',
+        'POST', REGISTRY_BASEURL + '/sync',
         content=servicetypetest_callback
     ) as matcher:
         yield matcher
@@ -132,7 +131,7 @@ def waveband_fixture(mocker):
         return get_pkg_data_contents('data/regtap.xml')
 
     with mocker.register_uri(
-        'POST', REGISTRY_BASEURL+'/sync',
+        'POST', REGISTRY_BASEURL + '/sync',
         content=wavebandtest_callback
     ) as matcher:
         yield matcher
@@ -154,7 +153,7 @@ def datamodel_fixture(mocker):
         return get_pkg_data_contents('data/regtap.xml')
 
     with mocker.register_uri(
-        'POST', REGISTRY_BASEURL+'/sync',
+        'POST', REGISTRY_BASEURL + '/sync',
         content=datamodeltest_callback
     ) as matcher:
         yield matcher
@@ -171,7 +170,7 @@ def aux_fixture(mocker):
         return get_pkg_data_contents('data/regtap.xml')
 
     with mocker.register_uri(
-        'POST', REGISTRY_BASEURL+'/sync',
+        'POST', REGISTRY_BASEURL + '/sync',
         content=auxtest_callback,
     ) as matcher:
         yield matcher
@@ -179,17 +178,17 @@ def aux_fixture(mocker):
 
 @pytest.fixture()
 def multi_interface_fixture(mocker):
-# to update this, run
-# import requests
-# from pyvo.registry import regtap
-#
-# with open("data/multi-interface.xml", "wb") as f:
-# 	f.write(requests.get(regtap.REGISTRY_BASEURL+"/sync", {
-# 		"LANG": "ADQL",
-# 		"QUERY": regtap.get_RegTAP_query(
-# 			ivoid="ivo://org.gavo.dc/flashheros/q/ssa")}).content)
+    # to update this, run
+    # import requests
+    # from pyvo.registry import regtap
+    #
+    # with open("data/multi-interface.xml", "wb") as f:
+    # 	f.write(requests.get(regtap.REGISTRY_BASEURL+"/sync", {
+    # 		"LANG": "ADQL",
+    # 		"QUERY": regtap.get_RegTAP_query(
+    # 			ivoid="ivo://org.gavo.dc/flashheros/q/ssa")}).content)
     with mocker.register_uri(
-        'POST', REGISTRY_BASEURL+'/sync',
+        'POST', REGISTRY_BASEURL + '/sync',
         content=get_pkg_data_contents('data/multi-interface.xml')
     ) as matcher:
         yield matcher
@@ -198,7 +197,7 @@ def multi_interface_fixture(mocker):
 @pytest.fixture()
 def flash_service(multi_interface_fixture):
     return regtap.search(
-            ivoid="ivo://org.gavo.dc/flashheros/q/ssa")[0]
+        ivoid="ivo://org.gavo.dc/flashheros/q/ssa")[0]
 
 
 class TestInterfaceClass:
@@ -208,22 +207,22 @@ class TestInterfaceClass:
         assert intf.standard_id is None
         assert intf.type is None
         assert intf.role is None
-        assert intf.is_standard == False
+        assert intf.is_standard is False
         assert not intf.is_vosi
 
     def test_repr(self):
         intf = regtap.Interface("http://example.org", "ivo://gavo/std/a",
-            "vs:paramhttp", "std")
+                                "vs:paramhttp", "std")
         assert (repr(intf) == "Interface('http://example.org',"
-            " 'ivo://gavo/std/a', 'vs:paramhttp', 'std')")
+                " 'ivo://gavo/std/a', 'vs:paramhttp', 'std')")
         intf = regtap.Interface("http://example.org", "ivo://gavo/std/a",
-            None, None)
+                                None, None)
         assert repr(intf) == ("Interface('http://example.org',"
-            " 'ivo://gavo/std/a', None, None)")
+                              " 'ivo://gavo/std/a', None, None)")
 
     def test_unknown_standard(self):
         intf = regtap.Interface("http://example.org", "ivo://gavo/std/a",
-            "vs:paramhttp", "std")
+                                "vs:paramhttp", "std")
         assert intf.is_standard
         with pytest.raises(ValueError) as excinfo:
             intf.to_service()
@@ -234,14 +233,14 @@ class TestInterfaceClass:
 
     def test_known_standard(self):
         intf = regtap.Interface("http://example.org",
-            "ivo://ivoa.net/std/tap#aux", "vs:paramhttp", "std")
+                                "ivo://ivoa.net/std/tap#aux", "vs:paramhttp", "std")
         assert isinstance(intf.to_service(), tap.TAPService)
         assert not intf.is_vosi
 
     def test_secondary_interface(self):
         intf = regtap.Interface("http://example.org",
-            "ivo://ivoa.net/std/tap#aux",
-            "vs:webbrowser", "web")
+                                "ivo://ivoa.net/std/tap#aux",
+                                "vs:webbrowser", "web")
 
         with pytest.raises(ValueError) as excinfo:
             intf.to_service()
@@ -251,8 +250,8 @@ class TestInterfaceClass:
 
     def test_VOSI(self):
         intf = regtap.Interface("http://example.org",
-            "ivo://ivoa.net/std/vosi#capabilities",
-            "vs:ParamHTTP", "std")
+                                "ivo://ivoa.net/std/vosi#capabilities",
+                                "vs:ParamHTTP", "std")
         assert intf.is_vosi
 
 
@@ -304,26 +303,26 @@ def test_bad_servicetype_aux():
 def test_spatial():
     assert (rtcons.keywords_to_constraints({
             "spatial": (23, -40)})[0].get_search_condition()
-        == "1 = CONTAINS(MOC(6, POINT(23, -40)), coverage)")
+            == "1 = CONTAINS(MOC(6, POINT(23, -40)), coverage)")
 
 
 def test_spectral():
     assert (rtcons.keywords_to_constraints({
-            "spectral": (1e-17, 2e-17)})[0].get_search_condition() ==
-        "1 = ivo_interval_overlaps(spectral_start, spectral_end, 1e-17, 2e-17)")
+            "spectral": (1e-17, 2e-17)})[0].get_search_condition()
+            == "1 = ivo_interval_overlaps(spectral_start, spectral_end, 1e-17, 2e-17)")
 
 
 def test_to_table(multi_interface_fixture, capabilities):
     t = regtap.search(
         ivoid="ivo://org.gavo.dc/flashheros/q/ssa").get_summary()
     assert (set(t.columns.keys())
-        == {'index', 'short_name', 'title', 'description', 'interfaces'})
+            == {'index', 'short_name', 'title', 'description', 'interfaces'})
     assert t["index"][0] == 0
     assert t["title"][0] == 'Flash/Heros SSAP'
     assert (t["description"][0][:40]
-        == 'Spectra from the Flash and Heros Echelle')
+            == 'Spectra from the Flash and Heros Echelle')
     assert (t["interfaces"][0]
-        == 'datalink#links-1.0, soda#sync-1.0, ssa, tap#aux, web')
+            == 'datalink#links-1.0, soda#sync-1.0, ssa, tap#aux, web')
 
 
 @pytest.fixture()
@@ -333,18 +332,18 @@ def rt_pulsar_distance(regtap_pulsar_distance_response, capabilities):
 
 def test_record_fields(rt_pulsar_distance):
     rec = rt_pulsar_distance["VII/156"]
-    assert rec.ivoid=="ivo://cds.vizier/vii/156"
-    assert rec.res_type=="vs:catalogservice"
-    assert rec.short_name=="VII/156"
-    assert rec.res_title=="Catalog of 558 Pulsars"
-    assert rec.content_levels==['research']
-    assert rec.res_description[:20]=="The catalogue is an up-to-date"[:20]
-    assert rec.reference_url=="http://cdsarc.unistra.fr/cgi-bin/cat/VII/156"
-    assert rec.creators==['Taylor J.H.', ' Manchester R.N.', ' Lyne A.G.']
-    assert rec.content_types==['catalog']
-    assert rec.source_format=="bibcode"
-    assert rec.source_value=="1993ApJS...88..529T"
-    assert rec.waveband==['radio']
+    assert rec.ivoid == "ivo://cds.vizier/vii/156"
+    assert rec.res_type == "vs:catalogservice"
+    assert rec.short_name == "VII/156"
+    assert rec.res_title == "Catalog of 558 Pulsars"
+    assert rec.content_levels == ['research']
+    assert rec.res_description[:20] == "The catalogue is an up-to-date"[:20]
+    assert rec.reference_url == "http://cdsarc.unistra.fr/cgi-bin/cat/VII/156"
+    assert rec.creators == ['Taylor J.H.', ' Manchester R.N.', ' Lyne A.G.']
+    assert rec.content_types == ['catalog']
+    assert rec.source_format == "bibcode"
+    assert rec.source_value == "1993ApJS...88..529T"
+    assert rec.waveband == ['radio']
     # access URL, standard_id and friends exercised in TestInterfaceSelection
 
 
@@ -352,21 +351,21 @@ class TestResultIndexing:
     def test_get_with_index(self, rt_pulsar_distance):
         # this is expecte to break when the fixture is updated
         assert (rt_pulsar_distance[0].res_title
-            == 'Pulsar Timing for Fermi Gamma-ray Space Telescope')
+                == 'Pulsar Timing for Fermi Gamma-ray Space Telescope')
 
     def test_get_with_short_name(self, rt_pulsar_distance):
         assert (rt_pulsar_distance["ATNF"].res_title
-            == 'ATNF Pulsar Catalog')
+                == 'ATNF Pulsar Catalog')
 
     def test_get_with_ivoid(self, rt_pulsar_distance):
         assert (rt_pulsar_distance["ivo://nasa.heasarc/atnfpulsar"
-            ].res_title == 'ATNF Pulsar Catalog')
+                                   ].res_title == 'ATNF Pulsar Catalog')
 
     def test_out_of_range(self, rt_pulsar_distance):
         with pytest.raises(IndexError) as excinfo:
             rt_pulsar_distance[40320]
         assert (str(excinfo.value)
-            == "index 40320 is out of bounds for axis 0 with size 23")
+                == "index 40320 is out of bounds for axis 0 with size 23")
 
     def test_bad_key(self, rt_pulsar_distance):
         with pytest.raises(KeyError) as excinfo:
@@ -377,16 +376,17 @@ class TestResultIndexing:
         with pytest.raises(IndexError) as excinfo:
             rt_pulsar_distance[None]
         assert (str(excinfo.value)
-            == "No resource matching None")
+                == "No resource matching None")
 
 
 @pytest.mark.usefixtures('multi_interface_fixture', 'capabilities',
-    'flash_service')
+                         'flash_service')
 class TestInterfaceSelection:
     """
     tests for the selection and generation of services within
     RegistryResource.
     """
+
     def test_exactly_one_result(self):
         results = regtap.search(
             ivoid="ivo://org.gavo.dc/flashheros/q/ssa")
@@ -402,33 +402,33 @@ class TestInterfaceSelection:
             _ = flash_service.standard_id
 
         assert str(excinfo.value) == ("This resource supports several"
-            " standards (datalink#links-1.0, soda#sync-1.0, ssa,"
-            " tap#aux, web).  Use get_service or restrict your query"
-            " using Servicetype.")
+                                      " standards (datalink#links-1.0, soda#sync-1.0, ssa,"
+                                      " tap#aux, web).  Use get_service or restrict your query"
+                                      " using Servicetype.")
 
     def test_get_web_interface(self, flash_service):
         svc = flash_service.get_service("web")
         assert isinstance(svc,
-            regtap._BrowserService)
+                          regtap._BrowserService)
         assert (svc.access_url
-            == "http://dc.zah.uni-heidelberg.de/flashheros/q/web/form")
+                == "http://dc.zah.uni-heidelberg.de/flashheros/q/web/form")
 
     def test_get_aux_interface(self, flash_service):
         svc = flash_service.get_service("tap#aux")
         assert (svc._baseurl
-            == "http://dc.zah.uni-heidelberg.de/tap")
+                == "http://dc.zah.uni-heidelberg.de/tap")
 
     def test_get_aux_as_main(self, flash_service):
         assert (flash_service.get_service("tap")._baseurl
-            == "http://dc.zah.uni-heidelberg.de/tap")
+                == "http://dc.zah.uni-heidelberg.de/tap")
 
     def test_get__main_from_aux(self, flash_service):
         assert (flash_service.get_service("tap")._baseurl
-            == "http://dc.zah.uni-heidelberg.de/tap")
+                == "http://dc.zah.uni-heidelberg.de/tap")
 
     def test_get_by_alias(self, flash_service):
         assert (flash_service.get_service("spectrum")._baseurl
-            == "http://dc.zah.uni-heidelberg.de/fhssa?")
+                == "http://dc.zah.uni-heidelberg.de/fhssa?")
 
     def test_get_unsupported_standard(self, flash_service):
         with pytest.raises(ValueError) as excinfo:
@@ -463,10 +463,11 @@ class _FakeResult:
     regtap.TOKEN_SEP -- this is how they ought to come in from
     RegTAP services.
     """
+
     def __init__(self, d):
         self.fieldnames = list(d.keys())
         vals = [regtap.TOKEN_SEP.join(v) if isinstance(v, list) else v
-            for v in d.values()]
+                for v in d.values()]
 
         class _:
             class array:
@@ -494,12 +495,13 @@ class TestInterfaceRejection:
     """tests for various artificial corner cases where interface selection
     should fail (or just not fail).
     """
+
     def test_nonunique(self):
         rsc = _makeRegistryRecord({
             "access_urls": ["http://a", "http://b"],
-            "standard_ids": ["ivo://ivoa.net/std/tap"]*2,
-            "intf_types": ["vs:paramhttp"]*2,
-            "intf_roles": ["std"]*2,
+            "standard_ids": ["ivo://ivoa.net/std/tap"] * 2,
+            "intf_types": ["vs:paramhttp"] * 2,
+            "intf_roles": ["std"] * 2,
         })
         with pytest.raises(ValueError) as excinfo:
             rsc.get_service("tap", lax=False)
@@ -512,24 +514,24 @@ class TestInterfaceRejection:
     def test_nonunique_lax(self):
         rsc = _makeRegistryRecord({
             "access_urls": ["http://a", "http://b"],
-            "standard_ids": ["ivo://ivoa.net/std/tap"]*2,
-            "intf_types": ["vs:paramhttp"]*2,
-            "intf_roles": ["std"]*2,
+            "standard_ids": ["ivo://ivoa.net/std/tap"] * 2,
+            "intf_types": ["vs:paramhttp"] * 2,
+            "intf_roles": ["std"] * 2,
         })
 
         assert (rsc.get_service("tap")._baseurl
-            == "http://a")
+                == "http://a")
 
     def test_nonstd_ignored(self):
         rsc = _makeRegistryRecord({
             "access_urls": ["http://a", "http://b"],
-            "standard_ids": ["ivo://ivoa.net/std/tap"]*2,
-            "intf_types": ["vs:paramhttp"]*2,
+            "standard_ids": ["ivo://ivoa.net/std/tap"] * 2,
+            "intf_types": ["vs:paramhttp"] * 2,
             "intf_roles": ["std", ""]
         })
 
         assert (rsc.get_service("tap", lax=False)._baseurl
-            == "http://a")
+                == "http://a")
 
     def test_select_single_matching_service(self):
         rsc = _makeRegistryRecord({
@@ -564,12 +566,12 @@ def test_get_contact():
     rsc = _makeRegistryRecord(
         {"ivoid": "ivo://org.gavo.dc/flashheros/q/ssa"})
     assert (rsc.get_contact()
-        == "GAVO Data Center Team (++49 6221 54 1837)"
+            == "GAVO Data Center Team (++49 6221 54 1837)"
             " <gavo@ari.uni-heidelberg.de>")
 
 
 @pytest.mark.usefixtures('multi_interface_fixture', 'capabilities',
-    'flash_service')
+                         'flash_service')
 class TestExtraResourceMethods:
     """
     tests for methods of RegistryResource containing some non-trivial
@@ -593,7 +595,7 @@ class TestExtraResourceMethods:
 
         assert "Flash/Heros SSAP" in output
         assert ("Access modes: datalink#links-1.0, soda#sync-1.0,"
-            " ssa, tap#aux, web" in output)
+                " ssa, tap#aux, web" in output)
         assert "Multi-capabilty service" in output
 
         assert "More info: http://dc.zah" in output
@@ -609,7 +611,7 @@ class TestExtraResourceMethods:
             rsc.access_url
 
         assert str(excinfo.value) == ("The resource"
-            " ivo://pyvo/test_regtap.py has no queriable interfaces.")
+                                      " ivo://pyvo/test_regtap.py has no queriable interfaces.")
 
     def test_unique_access_url(self):
         rsc = _makeRegistryRecord({
@@ -623,13 +625,13 @@ class TestExtraResourceMethods:
     def test_ambiguous_access_url_warns(self, recwarn):
         rsc = _makeRegistryRecord({
             "access_urls": ["http://a", "http://b"],
-            "standard_ids": ["ivo://ivoa.net/std/tap"]*2,
-            "intf_types": ["vs:paramhttp"]*2,
-            "intf_roles": ["std"]*2,
+            "standard_ids": ["ivo://ivoa.net/std/tap"] * 2,
+            "intf_types": ["vs:paramhttp"] * 2,
+            "intf_roles": ["std"] * 2,
         })
         assert rsc.access_url == "http://a"
         assert [str(w.message)[:50] for w in recwarn
-            ] == ['The resource ivo://pyvo/test_regtap.py has multipl']
+                ] == ['The resource ivo://pyvo/test_regtap.py has multipl']
 
 
 # TODO: While I suppose the contact test should keep requiring network,
@@ -653,31 +655,31 @@ class TestGetTables:
             rsc.get_tables()
 
         assert re.match(r"Resource ivo://org.gavo.dc/tap reports \d+ tables."
-            "  Pass a higher table_limit to see them all.", str(excinfo.value))
+                        "  Pass a higher table_limit to see them all.", str(excinfo.value))
 
     @pytest.mark.remote_data
     def test_get_tables_names(self, flash_tables):
         assert (list(sorted(flash_tables.keys()))
-            == ["flashheros.data", "ivoa.obscore"])
+                == ["flashheros.data", "ivoa.obscore"])
 
     @pytest.mark.remote_data
     def test_get_tables_table_instance(self, flash_tables):
         assert (flash_tables["ivoa.obscore"].name
-            == "ivoa.obscore")
+                == "ivoa.obscore")
         assert (flash_tables["ivoa.obscore"].description
-            == "This data collection is queryable in GAVO Data"
-            " Center's obscore table.")
+                == "This data collection is queryable in GAVO Data"
+                " Center's obscore table.")
         assert (flash_tables["flashheros.data"].title
-            == "Flash/Heros SSA table")
+                == "Flash/Heros SSA table")
 
         assert (flash_tables["flashheros.data"].origin.ivoid
-            == "ivo://org.gavo.dc/flashheros/q/ssa")
+                == "ivo://org.gavo.dc/flashheros/q/ssa")
 
     @pytest.mark.remote_data
     def test_get_tables_column_meta(self, flash_tables):
         def getflashcol(name):
             for col in flash_tables["flashheros.data"].columns:
-                if name==col.name:
+                if name == col.name:
                     return col
             raise KeyError(name)
 
@@ -693,7 +695,7 @@ class TestGetTables:
         assert getflashcol("ssa_specend").unit == "m"
 
         assert (getflashcol("ssa_specend").utype
-            == "ssa:char.spectralaxis.coverage.bounds.stop")
+                == "ssa:char.spectralaxis.coverage.bounds.stop")
 
         assert (getflashcol("ssa_fluxcalib").description
-            == "Type of flux calibration")
+                == "Type of flux calibration")
diff --git a/pyvo/registry/tests/test_rtcons.py b/pyvo/registry/tests/test_rtcons.py
index fea4f33..8d4e185 100644
--- a/pyvo/registry/tests/test_rtcons.py
+++ b/pyvo/registry/tests/test_rtcons.py
@@ -16,7 +16,7 @@ from pyvo import registry
 from pyvo.registry import rtcons
 from pyvo.dal import query as dalq
 
-from .commonfixtures import messenger_vocabulary
+from .commonfixtures import messenger_vocabulary  # noqa: F401
 
 
 class TestAbstractConstraint:
@@ -36,7 +36,7 @@ class TestSQLLiterals:
                 "anInt": 210,
                 "aFloat": 5e7,
                 "numpyStuff": numpy.float64(23.7),
-                "timestamp": datetime.datetime(2021, 6, 30, 9, 1),}
+                "timestamp": datetime.datetime(2021, 6, 30, 9, 1), }
 
         return _WithFillers()._get_sql_literals()
 
@@ -54,7 +54,7 @@ class TestSQLLiterals:
         assert literals["aFloat"] == "50000000.0"
 
     def test_numpy(self, literals):
-        assert float(literals["numpyStuff"])-23.7<1e-10
+        assert float(literals["numpyStuff"]) - 23.7 < 1e-10
 
     def test_timestamp(self, literals):
         assert literals["timestamp"] == "'2021-06-30T09:01:00'"
@@ -67,40 +67,44 @@ class TestSQLLiterals:
 
 class TestFreetextConstraint:
     def test_basic(self):
-        assert (rtcons.Freetext("star").get_search_condition()
-            == "ivoid IN (SELECT ivoid FROM rr.resource WHERE 1=ivo_hasword(res_description, 'star') UNION SELECT ivoid FROM rr.resource WHERE 1=ivo_hasword(res_title, 'star') UNION SELECT ivoid FROM rr.res_subject WHERE res_subject ILIKE '%star%')")
+        assert rtcons.Freetext("star").get_search_condition() == (
+            "ivoid IN (SELECT ivoid FROM rr.resource WHERE 1=ivo_hasword(res_description, 'star') "
+            "UNION SELECT ivoid FROM rr.resource WHERE 1=ivo_hasword(res_title, 'star') "
+            "UNION SELECT ivoid FROM rr.res_subject WHERE res_subject ILIKE '%star%')")
 
     def test_interesting_literal(self):
-        assert (rtcons.Freetext("α Cen's planets").get_search_condition()
-            == "ivoid IN (SELECT ivoid FROM rr.resource WHERE 1=ivo_hasword(res_description, 'α Cen''s planets') UNION SELECT ivoid FROM rr.resource WHERE 1=ivo_hasword(res_title, 'α Cen''s planets') UNION SELECT ivoid FROM rr.res_subject WHERE res_subject ILIKE '%α Cen''s planets%')")
+        assert rtcons.Freetext("α Cen's planets").get_search_condition() == (
+            "ivoid IN (SELECT ivoid FROM rr.resource WHERE 1=ivo_hasword(res_description, 'α Cen''s planets')"
+            " UNION SELECT ivoid FROM rr.resource WHERE 1=ivo_hasword(res_title, 'α Cen''s planets')"
+            " UNION SELECT ivoid FROM rr.res_subject WHERE res_subject ILIKE '%α Cen''s planets%')")
 
 
 class TestAuthorConstraint:
     def test_basic(self):
         assert (rtcons.Author("%Hubble%").get_search_condition()
-            == "role_name LIKE '%Hubble%' AND base_role='creator'")
+                == "role_name LIKE '%Hubble%' AND base_role='creator'")
 
 
 class TestServicetypeConstraint:
     def test_standardmap(self):
         assert (rtcons.Servicetype("scs").get_search_condition()
-            == "standard_id IN ('ivo://ivoa.net/std/conesearch')")
+                == "standard_id IN ('ivo://ivoa.net/std/conesearch')")
 
     def test_fulluri(self):
         assert (rtcons.Servicetype("http://extstandards/invention"
-                ).get_search_condition()
-            == "standard_id IN ('http://extstandards/invention')")
+                                   ).get_search_condition()
+                == "standard_id IN ('http://extstandards/invention')")
 
     def test_multi(self):
         assert (rtcons.Servicetype("http://extstandards/invention", "image"
-                ).get_search_condition()
-            == "standard_id IN ('http://extstandards/invention',"
+                                   ).get_search_condition()
+                == "standard_id IN ('http://extstandards/invention',"
                 " 'ivo://ivoa.net/std/sia')")
 
     def test_includeaux(self):
         assert (rtcons.Servicetype("http://extstandards/invention", "image"
-                ).include_auxiliary_services().get_search_condition()
-            == "standard_id IN ('http://extstandards/invention',"
+                                   ).include_auxiliary_services().get_search_condition()
+                == "standard_id IN ('http://extstandards/invention',"
                 " 'http://extstandards/invention#aux',"
                 " 'ivo://ivoa.net/std/sia',"
                 " 'ivo://ivoa.net/std/sia#aux')")
@@ -109,30 +113,31 @@ class TestServicetypeConstraint:
         with pytest.raises(dalq.DALQueryError) as excinfo:
             rtcons.Servicetype("junk")
         assert str(excinfo.value) == ("Service type junk is neither"
-            " a full standard URI nor one of the bespoke identifiers"
-            " image, sia, spectrum, ssap, ssa, scs, conesearch, line, slap,"
-            " table, tap")
+                                      " a full standard URI nor one of the bespoke identifiers"
+                                      " image, sia, spectrum, ssap, ssa, scs, conesearch, line, slap,"
+                                      " table, tap")
 
     def test_legacy_term(self):
         assert (rtcons.Servicetype("conesearch").get_search_condition()
-            == "standard_id IN ('ivo://ivoa.net/std/conesearch')")
+                == "standard_id IN ('ivo://ivoa.net/std/conesearch')")
 
 
 @pytest.mark.usefixtures('messenger_vocabulary')
 class TestWavebandConstraint:
     def test_basic(self):
         assert (rtcons.Waveband("Infrared", "EUV").get_search_condition()
-            == "1 = ivo_hashlist_has(rr.resource.waveband, 'infrared')"
+                == "1 = ivo_hashlist_has(rr.resource.waveband, 'infrared')"
                 " OR 1 = ivo_hashlist_has(rr.resource.waveband, 'euv')")
 
     def test_junk_rejected(self):
         with pytest.raises(dalq.DALQueryError) as excinfo:
             rtcons.Waveband("junk")
-        assert str(excinfo.value) == ("Waveband junk is not in the IVOA messenger vocabulary http://www.ivoa.net/rdf/messenger.")
+        assert str(excinfo.value) == (
+            "Waveband junk is not in the IVOA messenger vocabulary http://www.ivoa.net/rdf/messenger.")
 
     def test_normalisation(self):
         assert (rtcons.Waveband("oPtIcAl").get_search_condition()
-            == "1 = ivo_hashlist_has(rr.resource.waveband, 'optical')")
+                == "1 = ivo_hashlist_has(rr.resource.waveband, 'optical')")
 
 
 class TestDatamodelConstraint:
@@ -145,75 +150,69 @@ class TestDatamodelConstraint:
     def test_obscore(self):
         cons = rtcons.Datamodel("ObsCore")
         assert (cons.get_search_condition()
-            == "detail_xpath = '/capability/dataModel/@ivo-id'"
-            " AND 1 = ivo_nocasematch(detail_value,"
+                == "detail_xpath = '/capability/dataModel/@ivo-id'"
+                " AND 1 = ivo_nocasematch(detail_value,"
                 " 'ivo://ivoa.net/std/obscore%')")
-        assert(cons._extra_tables==["rr.res_detail"])
+        assert (cons._extra_tables == ["rr.res_detail"])
 
     def test_epntap(self):
         cons = rtcons.Datamodel("epntap")
         assert (cons.get_search_condition()
-            == "table_utype LIKE ivo://vopdc.obspm/std/epncore#schema-2.%'"
-            " OR table_utype LIKE ivo://ivoa.net/std/epntap#table-2.%'")
-        assert(cons._extra_tables==["rr.res_table"])
+                == "table_utype LIKE ivo://vopdc.obspm/std/epncore#schema-2.%'"
+                " OR table_utype LIKE ivo://ivoa.net/std/epntap#table-2.%'")
+        assert (cons._extra_tables == ["rr.res_table"])
 
     def test_regtap(self):
         cons = rtcons.Datamodel("regtap")
         assert (cons.get_search_condition()
-            == "detail_xpath = '/capability/dataModel/@ivo-id'"
-            " AND 1 = ivo_nocasematch(detail_value,"
+                == "detail_xpath = '/capability/dataModel/@ivo-id'"
+                " AND 1 = ivo_nocasematch(detail_value,"
                 " 'ivo://ivoa.net/std/RegTAP#1.%')")
-        assert(cons._extra_tables==["rr.res_detail"])
+        assert (cons._extra_tables == ["rr.res_detail"])
 
 
 class TestIvoidConstraint:
     def test_basic(self):
         cons = rtcons.Ivoid("ivo://example/some_path")
-        assert (cons.get_search_condition() ==
-            "ivoid = 'ivo://example/some_path'")
+        assert (cons.get_search_condition()
+                == "ivoid = 'ivo://example/some_path'")
 
 
 class TestUCDConstraint:
     def test_basic(self):
         cons = rtcons.UCD("phot.mag;em.opt.%", "phot.mag;em.ir.%")
-        assert (cons.get_search_condition() ==
-            "ucd LIKE 'phot.mag;em.opt.%' OR ucd LIKE 'phot.mag;em.ir.%'")
+        assert (cons.get_search_condition()
+                == "ucd LIKE 'phot.mag;em.opt.%' OR ucd LIKE 'phot.mag;em.ir.%'")
 
 
 class TestSpatialConstraint:
     def test_point(self):
         cons = registry.Spatial([23, -40])
-        assert (cons.get_search_condition() ==
-            "1 = CONTAINS(MOC(6, POINT(23, -40)), coverage)")
-        assert(cons._extra_tables==["rr.stc_spatial"])
+        assert cons.get_search_condition() == "1 = CONTAINS(MOC(6, POINT(23, -40)), coverage)"
+        assert cons._extra_tables == ["rr.stc_spatial"]
 
     def test_circle_and_order(self):
         cons = registry.Spatial([23, -40, 0.25], order=7)
-        assert (cons.get_search_condition() ==
-            "1 = CONTAINS(MOC(7, CIRCLE(23, -40, 0.25)), coverage)")
+        assert cons.get_search_condition() == "1 = CONTAINS(MOC(7, CIRCLE(23, -40, 0.25)), coverage)"
 
     def test_polygon(self):
         cons = registry.Spatial([23, -40, 26, -39, 25, -43])
-        assert (cons.get_search_condition() ==
-            "1 = CONTAINS(MOC(6, POLYGON(23, -40, 26, -39, 25, -43)),"
-                " coverage)")
+        assert cons.get_search_condition() == (
+            "1 = CONTAINS(MOC(6, POLYGON(23, -40, 26, -39, 25, -43)), coverage)")
 
     def test_moc(self):
         cons = registry.Spatial("0/1-3 3/")
-        assert (cons.get_search_condition() ==
-            "1 = CONTAINS(MOC('0/1-3 3/'), coverage)")
+        assert cons.get_search_condition() == "1 = CONTAINS(MOC('0/1-3 3/'), coverage)"
 
     def test_SkyCoord(self):
-        cons = registry.Spatial(SkyCoord(3*units.deg, -30*units.deg))
-        assert (cons.get_search_condition() ==
-            "1 = CONTAINS(MOC(6, POINT(3.0, -30.0)), coverage)")
-        assert(cons._extra_tables==["rr.stc_spatial"])
+        cons = registry.Spatial(SkyCoord(3 * units.deg, -30 * units.deg))
+        assert cons.get_search_condition() == "1 = CONTAINS(MOC(6, POINT(3.0, -30.0)), coverage)"
+        assert cons._extra_tables == ["rr.stc_spatial"]
 
     def test_SkyCoord_Circle(self):
-        cons = registry.Spatial((SkyCoord(3*units.deg, -30*units.deg), 3))
-        assert (cons.get_search_condition() ==
-            "1 = CONTAINS(MOC(6, CIRCLE(3.0, -30.0, 3)), coverage)")
-        assert(cons._extra_tables==["rr.stc_spatial"])
+        cons = registry.Spatial((SkyCoord(3 * units.deg, -30 * units.deg), 3))
+        assert cons.get_search_condition() == "1 = CONTAINS(MOC(6, CIRCLE(3.0, -30.0, 3)), coverage)"
+        assert cons._extra_tables == ["rr.stc_spatial"]
 
 
 class TestSpectralConstraint:
@@ -222,98 +221,92 @@ class TestSpectralConstraint:
     # that would be useful there.
     def test_energy_float(self):
         cons = registry.Spectral(1e-19)
-        assert (cons.get_search_condition() ==
-            "1e-19 BETWEEN spectral_start AND spectral_end")
+        assert cons.get_search_condition() == "1e-19 BETWEEN spectral_start AND spectral_end"
 
     def test_energy_eV(self):
-        cons = registry.Spectral(5*units.eV)
-        assert (cons.get_search_condition() ==
-            "8.01088317e-19 BETWEEN spectral_start AND spectral_end")
+        cons = registry.Spectral(5 * units.eV)
+        assert cons.get_search_condition() == "8.01088317e-19 BETWEEN spectral_start AND spectral_end"
 
     def test_energy_interval(self):
-        cons = registry.Spectral((1e-10*units.erg, 2e-10*units.erg))
-        assert (cons.get_search_condition() ==
-            "1 = ivo_interval_overlaps(spectral_start, spectral_end,"
-            " 1e-17, 2e-17)")
+        cons = registry.Spectral((1e-10 * units.erg, 2e-10 * units.erg))
+        assert cons.get_search_condition() == (
+            "1 = ivo_interval_overlaps(spectral_start, spectral_end, 1e-17, 2e-17)")
 
     def test_wavelength(self):
-        cons = registry.Spectral(5000*units.Angstrom)
-        assert (cons.get_search_condition() ==
-            "3.9728917142978567e-19 BETWEEN spectral_start AND spectral_end")
+        cons = registry.Spectral(5000 * units.Angstrom)
+        assert cons.get_search_condition() == "3.9728917142978567e-19 BETWEEN spectral_start AND spectral_end"
 
     def test_wavelength_interval(self):
-        cons = registry.Spectral((20*units.cm, 22*units.cm))
-        assert (cons.get_search_condition() ==
-            "1 = ivo_interval_overlaps(spectral_start, spectral_end,"
-            " 9.932229285744642e-25, 9.029299350676949e-25)")
+        cons = registry.Spectral((20 * units.cm, 22 * units.cm))
+        assert (cons.get_search_condition()
+                == "1 = ivo_interval_overlaps(spectral_start, spectral_end,"
+                " 9.932229285744642e-25, 9.029299350676949e-25)")
 
     def test_frequency(self):
-        cons = registry.Spectral(2*units.GHz)
-        assert (cons.get_search_condition() ==
-            "1.32521403e-24 BETWEEN spectral_start AND spectral_end")
+        cons = registry.Spectral(2 * units.GHz)
+        assert (cons.get_search_condition()
+                == "1.32521403e-24 BETWEEN spectral_start AND spectral_end")
 
     def test_frequency_interval(self):
-        cons = registry.Spectral((88*units.MHz, 102*units.MHz))
-        assert (cons.get_search_condition() ==
-            "1 = ivo_interval_overlaps(spectral_start, spectral_end,"
-            " 5.830941732e-26, 6.758591553e-26)")
+        cons = registry.Spectral((88 * units.MHz, 102 * units.MHz))
+        assert (cons.get_search_condition()
+                == "1 = ivo_interval_overlaps(spectral_start, spectral_end,"
+                " 5.830941732e-26, 6.758591553e-26)")
 
 
 class TestTemporalConstraint:
     def test_plain_float(self):
         cons = registry.Temporal((54130, 54200))
-        assert (cons.get_search_condition() ==
-            "1 = ivo_interval_overlaps(time_start, time_end,"
-            " 54130, 54200)")
+        assert (cons.get_search_condition()
+                == "1 = ivo_interval_overlaps(time_start, time_end, 54130, 54200)")
 
     def test_single_time(self):
         cons = registry.Temporal(time.Time('2022-01-10'))
-        assert (cons.get_search_condition() ==
-            "59589.0 BETWEEN time_start AND time_end")
+        assert (cons.get_search_condition()
+                == "59589.0 BETWEEN time_start AND time_end")
 
     def test_time_interval(self):
         cons = registry.Temporal((time.Time(2459000, format='jd'),
-            time.Time(59002, format='mjd')))
-        assert (cons.get_search_condition() ==
-            "1 = ivo_interval_overlaps(time_start, time_end, 58999.5, 59002.0)")
+                                  time.Time(59002, format='mjd')))
+        assert (cons.get_search_condition()
+                == "1 = ivo_interval_overlaps(time_start, time_end, 58999.5, 59002.0)")
 
     def test_multi_times_rejected(self):
         with pytest.raises(ValueError) as excinfo:
-            cons = registry.Temporal(time.Time(['1999-01-01', '2010-01-01']))
+            registry.Temporal(time.Time(['1999-01-01', '2010-01-01']))
         assert (str(excinfo.value) == "RegTAP time constraints must"
-            " be made from single time instants.")
+                " be made from single time instants.")
 
 
 class TestWhereClauseBuilding:
     @staticmethod
     def where_clause_for(*args, **kwargs):
-        cons = list(args)+rtcons.keywords_to_constraints(kwargs)
-        return rtcons.build_regtap_query(cons
-            ).split("\nWHERE\n", 1)[1].split("\nGROUP BY\n")[0]
+        cons = list(args) + rtcons.keywords_to_constraints(kwargs)
+        return rtcons.build_regtap_query(cons).split("\nWHERE\n", 1)[1].split("\nGROUP BY\n")[0]
 
     @pytest.mark.usefixtures('messenger_vocabulary')
     def test_from_constraints(self):
         assert self.where_clause_for(
             rtcons.Waveband("EUV"),
             rtcons.Author("%Hubble%")
-            ) == ("(1 = ivo_hashlist_has(rr.resource.waveband, 'euv'))\n"
-                "  AND (role_name LIKE '%Hubble%' AND base_role='creator')")
+        ) == ("(1 = ivo_hashlist_has(rr.resource.waveband, 'euv'))\n"
+              "  AND (role_name LIKE '%Hubble%' AND base_role='creator')")
 
     @pytest.mark.usefixtures('messenger_vocabulary')
     def test_from_keywords(self):
         assert self.where_clause_for(
             waveband="EUV",
             author="%Hubble%"
-            ) == ("(1 = ivo_hashlist_has(rr.resource.waveband, 'euv'))\n"
-                "  AND (role_name LIKE '%Hubble%' AND base_role='creator')")
+        ) == ("(1 = ivo_hashlist_has(rr.resource.waveband, 'euv'))\n"
+              "  AND (role_name LIKE '%Hubble%' AND base_role='creator')")
 
     @pytest.mark.usefixtures('messenger_vocabulary')
     def test_mixed(self):
         assert self.where_clause_for(
             rtcons.Waveband("EUV"),
             author="%Hubble%"
-            ) == ("(1 = ivo_hashlist_has(rr.resource.waveband, 'euv'))\n"
-                "  AND (role_name LIKE '%Hubble%' AND base_role='creator')")
+        ) == ("(1 = ivo_hashlist_has(rr.resource.waveband, 'euv'))\n"
+              "  AND (role_name LIKE '%Hubble%' AND base_role='creator')")
 
     def test_bad_keyword(self):
         with pytest.raises(TypeError) as excinfo:
@@ -324,22 +317,22 @@ class TestWhereClauseBuilding:
         # way to track changes; so, let's update the assertion as we
         # go.
         assert str(excinfo.value) == ("foo is not a valid registry"
-            " constraint keyword.  Use one of"
-            " author, datamodel, ivoid, keywords, servicetype,"
-            " spatial, spectral, temporal, ucd, waveband.")
+                                      " constraint keyword.  Use one of"
+                                      " author, datamodel, ivoid, keywords, servicetype,"
+                                      " spatial, spectral, temporal, ucd, waveband.")
 
     def test_with_legacy_keyword(self):
         assert self.where_clause_for(
             "plain", "string"
-            ) == (
+        ) == (
             '(ivoid IN (SELECT ivoid FROM rr.resource WHERE '
-             "1=ivo_hasword(res_description, 'plain') UNION SELECT ivoid FROM rr.resource "
-             "WHERE 1=ivo_hasword(res_title, 'plain') UNION SELECT ivoid FROM "
-             "rr.res_subject WHERE res_subject ILIKE '%plain%'))\n"
-             '  AND (ivoid IN (SELECT ivoid FROM rr.resource WHERE '
-             "1=ivo_hasword(res_description, 'string') UNION SELECT ivoid FROM rr.resource "
-             "WHERE 1=ivo_hasword(res_title, 'string') UNION SELECT ivoid FROM "
-             "rr.res_subject WHERE res_subject ILIKE '%string%'))")
+            "1=ivo_hasword(res_description, 'plain') UNION SELECT ivoid FROM rr.resource "
+            "WHERE 1=ivo_hasword(res_title, 'plain') UNION SELECT ivoid FROM "
+            "rr.res_subject WHERE res_subject ILIKE '%plain%'))\n"
+            '  AND (ivoid IN (SELECT ivoid FROM rr.resource WHERE '
+            "1=ivo_hasword(res_description, 'string') UNION SELECT ivoid FROM rr.resource "
+            "WHERE 1=ivo_hasword(res_title, 'string') UNION SELECT ivoid FROM "
+            "rr.res_subject WHERE res_subject ILIKE '%string%'))")
 
 
 class TestSelectClause:
@@ -348,7 +341,7 @@ class TestSelectClause:
         # is changed.  Just update the assertion then.
         assert rtcons.build_regtap_query(
             rtcons.keywords_to_constraints({"author": "%Hubble%"})
-            ).split("\nFROM\nrr.resource\n")[0] == (
+        ).split("\nFROM\nrr.resource\n")[0] == (
             "SELECT\n"
             "ivoid, "
             "res_type, "
@@ -372,7 +365,7 @@ class TestSelectClause:
         # Again, this will break as regtap.RegistryResource.expected_columns
         # is changed.  Just update the assertion then.
         assert rtcons.build_regtap_query([rtcons.Author("%Hubble%")]
-            ).split("\nGROUP BY\n")[-1] == (
+                                         ).split("\nGROUP BY\n")[-1] == (
             "ivoid, "
             "res_type, "
             "short_name, "
diff --git a/pyvo/samp.py b/pyvo/samp.py
index 559641e..f864a50 100644
--- a/pyvo/samp.py
+++ b/pyvo/samp.py
@@ -36,8 +36,8 @@ def send_table_to(conn, table, client_name=None, name="data"):
         message = {
             "samp.mtype": "table.load.votable",
             "samp.params": {
-               "url": url,
-               "name": name,
+                "url": url,
+                "name": name,
             },
         }
         if client_name is None:
@@ -87,7 +87,7 @@ def send_image_to(conn, url, client_name=None, name="data"):
     asks an image client to open a remote image via SAMP.
     """
     send_product_to(
-        conn,  url, "image.load.fits",
+        conn, url, "image.load.fits",
         client_name=client_name, name=name)
 
 
diff --git a/pyvo/utils/formatting.py b/pyvo/utils/formatting.py
index c8a1979..6f02170 100644
--- a/pyvo/utils/formatting.py
+++ b/pyvo/utils/formatting.py
@@ -35,7 +35,7 @@ def para_format_desc(text, width=78):
 
 
 _musubs = [
-    (re.compile(r"&lt;"), "<"),  (re.compile(r"&gt;"), ">"),
+    (re.compile(r"&lt;"), "<"), (re.compile(r"&gt;"), ">"),
     (re.compile(r"&amp;"), "&"), (re.compile(r"<br\s*/?>"), ''),
     (re.compile(r"</p>"), ''), (re.compile(r"&#176;"), " deg"),
     (re.compile(r"\$((?:[^\$]*[\*\+=/^_~><\\][^\$]*)|(?:\w+))\$"), r'\1'),
diff --git a/pyvo/utils/protofeature.py b/pyvo/utils/protofeature.py
index 7e4d4ce..c5bf146 100644
--- a/pyvo/utils/protofeature.py
+++ b/pyvo/utils/protofeature.py
@@ -6,10 +6,11 @@ __all__ = ['Feature']
 @dataclass
 class Feature:
     """
-    A prototype feature implementing a standard that is currently in the process of being approved, but that might
-    change as a result of the approval process. A Feature must have a name. Optionally, a feature may have a *url*
-    that is displayed to the user in case a feature is used without the user explicitly opting in on its usage.
-    The URL is expected to contain more information about the standard and its state in the approval process.
+    A prototype feature implementing a standard that is currently in the process of being
+    approved, but that might change as a result of the approval process. A Feature must
+    have a name. Optionally, a feature may have a *url* that is displayed to the user in
+    case a feature is used without the user explicitly opting in on its usage. The URL is
+    expected to contain more information about the standard and its state in the approval process.
     """
     name: str
     url: str = ''
@@ -29,9 +30,9 @@ class Feature:
         """
         Format an error message when the feature is being accesses without the user having opted in its usage.
 
-        This function will be used as a callback when an error message needs to be displayed to the user, with the
-        function name that was accessed as an argument. Extensions of this class may have additional information to
-        display.
+        This function will be used as a callback when an error message needs to be displayed to
+        the user, with the function name that was accessed as an argument. Extensions of this
+        class may have additional information to display.
 
         Parameters
         ----------
@@ -43,10 +44,11 @@ class Feature:
         str: The error message to be displayed to the user.
 
         """
-        message = f'{function_name} is part of a prototype feature ({self.name}) that has not been activated. ' \
-                  f'For information about prototype features please refer to ' \
-                  f'https://pyvo.readthedocs.io/en/latest/utils/prototypes.html .'
+        message = (f'{function_name} is part of a prototype feature ({self.name}) that has not '
+                   'been activated. For information about prototype features please refer to '
+                   'https://pyvo.readthedocs.io/en/latest/utils/prototypes.html .')
         if self.url:
             message += f' For more information about the {self.name} feature please visit {self.url}.'
-        message += f' To suppress this error and enable the feature use `pyvo.utils.activate_features(\'{self.name}\')`'
+        message += (" To suppress this error and enable the feature use "
+                    f"`pyvo.utils.activate_features('{self.name}')`")
         return message
diff --git a/pyvo/utils/prototype.py b/pyvo/utils/prototype.py
index 7dc4cbc..9dbc836 100644
--- a/pyvo/utils/prototype.py
+++ b/pyvo/utils/prototype.py
@@ -10,13 +10,16 @@ __all__ = ['features', 'prototype_feature', 'activate_features', 'PrototypeWarni
 
 
 features: Dict[str, "Feature"] = {
-'cadc-tb-upload': Feature('cadc-tb-upload', 'https://wiki.ivoa.net/twiki/bin/view/IVOA/TAP-1_1-Next', False)
+    'cadc-tb-upload': Feature('cadc-tb-upload',
+                              'https://wiki.ivoa.net/twiki/bin/view/IVOA/TAP-1_1-Next',
+                              False)
 }
 
 
 def prototype_feature(*args):
     """
-    Decorator for functions and classes that implement unstable standards which haven't been approved yet.
+    Decorator for functions and classes that implement unstable standards
+    which haven't been approved yet.
     The decorator can be used to tag individual functions or methods.
 
     Please refer to the user documentation for details.
@@ -24,13 +27,16 @@ def prototype_feature(*args):
     Parameters
     ----------
     args: iterable of arguments.
-        Currently, the decorator must always be called with one and only one argument, a string representing
-        the feature's name associated with the decorated class or functions. Additional arguments will be ignored,
-        while using the decorator without any arguments will result in a ``PrototypeError`` error.
+        Currently, the decorator must always be called with one and only one
+        argument, a string representing the feature's name associated with
+        the decorated class or functions. Additional arguments will be ignored,
+        while using the decorator without any arguments will result in a
+        ``PrototypeError`` error.
 
     Returns
     -------
-    The class or function it decorates, which will be associated to the feature provided as argument.
+    The class or function it decorates, which will be associated to the
+    feature provided as argument.
 
     """
     feature_name = _parse_args(*args)
@@ -53,8 +59,9 @@ def activate_features(*feature_names: Iterable[str]):
     Parameters
     ----------
     feature_names: Iterable[str]
-        An arbitrary number of feature names. If a feature with that name does not exist, a `PrototypeWarning` will
-        be issued. If no arguments are provided, all features will be activated
+        An arbitrary number of feature names. If a feature with that name does
+        not exist, a `PrototypeWarning` will be issued. If no arguments are
+        provided, all features will be activated
 
     Returns
     -------
@@ -70,8 +77,9 @@ def deactivate_features(*feature_names: Iterable[str]):
     Parameters
     ----------
     feature_names: Iterable[str]
-        An arbitrary number of feature names. If a feature with that name does not exist, a `PrototypeWarning` will
-        be issued. If no arguments are provided, all features will be de-activated
+        An arbitrary number of feature names. If a feature with that name does
+        not exist, a `PrototypeWarning` will be issued. If no arguments are
+        provided, all features will be de-activated
 
     Returns
     -------
@@ -90,8 +98,8 @@ class PrototypeWarning(PyvoUserWarning):
 
 def _parse_args(*args):
     if not args or callable(args[0]):
-        raise PrototypeError("The `prototype_feature` decorator must always be called with the feature name as an "
-                             "argument")
+        raise PrototypeError("The `prototype_feature` decorator must always be called with the "
+                             "feature name as an argument")
     return args[0]
 
 
diff --git a/pyvo/utils/tests/test_http.py b/pyvo/utils/tests/test_http.py
index efc78ee..884c9b8 100644
--- a/pyvo/utils/tests/test_http.py
+++ b/pyvo/utils/tests/test_http.py
@@ -9,6 +9,5 @@ from pyvo.version import version
 
 
 def test_create_session():
-    system = platform.system()
     test_session = create_session()
     assert test_session.headers['User-Agent'] == 'python-pyvo/{} ({})'.format(version, platform.system())
diff --git a/pyvo/utils/tests/test_prototype.py b/pyvo/utils/tests/test_prototype.py
index 3466380..98546f3 100644
--- a/pyvo/utils/tests/test_prototype.py
+++ b/pyvo/utils/tests/test_prototype.py
@@ -1,4 +1,3 @@
-import warnings
 from copy import deepcopy
 from unittest import mock
 
@@ -39,7 +38,8 @@ def test_feature_turned_off_by_default(prototype_function):
     with pytest.raises(PrototypeError) as e:
         prototype_function(None)
 
-    assert 'i_am_prototype is part of a prototype feature (my-feature) that has not been activated. ' in str(e.value)
+    assert 'i_am_prototype is part of a prototype feature (my-feature) that has not been activated. ' in str(
+        e.value)
     assert 'please visit http://somewhere/else' in str(e.value)
     assert 'https://pyvo.readthedocs.io/en/latest/utils/prototypes.html' in str(e.value)
     assert "pyvo.utils.activate_features('my-feature')" in str(e.value)
@@ -127,8 +127,8 @@ def test_decorator_without_args_errors_out():
         def function():
             pass
 
-    assert str(e.value) == "The `prototype_feature` decorator must always be called with the feature name as an " \
-                           "argument"
+    assert str(e.value) == ("The `prototype_feature` decorator must always be called with the feature "
+                            "name as an argument")
 
 
 def test_decorator_without_args_around_class():
@@ -137,8 +137,8 @@ def test_decorator_without_args_around_class():
         class Class:
             pass
 
-    assert str(e.value) == "The `prototype_feature` decorator must always be called with the feature name as an " \
-                           "argument"
+    assert str(e.value) == ("The `prototype_feature` decorator must always be called with the feature "
+                            "name as an argument")
 
 
 def test_decorator_with_no_arguments_and_class():
@@ -147,5 +147,5 @@ def test_decorator_with_no_arguments_and_class():
         class Class:
             pass
 
-    assert str(e.value) == "The `prototype_feature` decorator must always be called with the feature name as an " \
-                           "argument"
+    assert str(e.value) == ("The `prototype_feature` decorator must always be called with the feature "
+                            "name as an argument")
diff --git a/pyvo/utils/tests/test_vocabularies_remote.py b/pyvo/utils/tests/test_vocabularies_remote.py
index 702fa3f..e8ce876 100644
--- a/pyvo/utils/tests/test_vocabularies_remote.py
+++ b/pyvo/utils/tests/test_vocabularies_remote.py
@@ -33,7 +33,7 @@ class TestVocabularies:
     def test_label_getting(self):
         voc = vocabularies.get_vocabulary("datalink/core")
         assert (vocabularies.get_label(voc, "coderived")
-            == "Coderived Data")
+                == "Coderived Data")
 
     def test_label_getting_default(self):
         voc = vocabularies.get_vocabulary("datalink/core")
@@ -53,7 +53,7 @@ class TestVocabularies:
             last_change = 0
             for entry in entries:
                 last_change = max(last_change, entry.stat().st_mtime)
-        assert time.time()-last_change<2
+        assert time.time() - last_change < 2
 
     def test_non_existing_voc(self):
         with pytest.raises(vocabularies.VocabularyError):
@@ -65,24 +65,24 @@ class TestVocabularies:
         fake_voc = "http://www.ivoa.net/rdf/astropy-test-failure"
 
         cache_dir = pathlib.Path(data._get_download_cache_loc()
-            )/data._url_to_dirname(fake_voc)
+                                 ) / data._url_to_dirname(fake_voc)
         cache_dir.mkdir(exist_ok=True)
 
-        cache_name = cache_dir/"contents"
+        cache_name = cache_dir / "contents"
         with open(cache_name, "w") as f:
             f.write("{}")
-        with open(cache_dir/"url", "w") as f:
+        with open(cache_dir / "url", "w") as f:
             f.write(fake_voc)
         os.utime(cache_name, (1000000000, 1000000000))
 
         with pytest.warns(PyvoUserWarning) as msgs:
-            voc = vocabularies.get_vocabulary("astropy-test-failure")
+            vocabularies.get_vocabulary("astropy-test-failure")
         # this sometimes catches a warning about an unclosed socket that,
         # I think, originates somewhere else; let me work around it for
         # the moment.
         for msg in msgs:
             if str(msg.message) == ("Updating cache for the vocabulary"
-                " astropy-test-failure failed: HTTP Error 404: Not Found"):
+                                    " astropy-test-failure failed: HTTP Error 404: Not Found"):
                 break
         else:
             raise AssertionError("No warning about failed cache update")
diff --git a/pyvo/utils/vocabularies.py b/pyvo/utils/vocabularies.py
index ee28e73..9b67ca5 100644
--- a/pyvo/utils/vocabularies.py
+++ b/pyvo/utils/vocabularies.py
@@ -11,7 +11,6 @@ import json
 import os
 import time
 import warnings
-from urllib import request
 
 from astropy.utils.data import download_file, clear_download_cache
 
@@ -36,7 +35,7 @@ def get_vocabulary(voc_name, force_update=False):
     This will use a cache to avoid repeated updates, but it
     will attempt to re-download if the cached copy is older than 6 months.
     """
-    src_url = IVOA_VOCABULARY_ROOT+voc_name
+    src_url = IVOA_VOCABULARY_ROOT + voc_name
     if force_update:
         clear_download_cache(src_url)
 
@@ -50,17 +49,17 @@ def get_vocabulary(voc_name, force_update=False):
         raise VocabularyError("No such vocabulary: {} ({})".format(
             voc_name, msg))
 
-    if time.time()-os.path.getmtime(src_name)>3600*60*150:
+    if time.time() - os.path.getmtime(src_name) > 3600 * 60 * 150:
         # attempt a re-retrieval, but ignore failure
         try:
             src_name = download_file(
-                IVOA_VOCABULARY_ROOT+voc_name,
+                IVOA_VOCABULARY_ROOT + voc_name,
                 cache="update", show_progress=False,
                 http_headers={"accept": "application/x-desise+json"})
         except Exception as msg:
             warnings.warn("Updating cache for the vocabulary"
-                f" {voc_name} failed: {msg}",
-                category=PyvoUserWarning)
+                          f" {voc_name} failed: {msg}",
+                          category=PyvoUserWarning)
 
     with open(src_name, "r", encoding="utf-8") as f:
         return json.load(f)
diff --git a/pyvo/utils/xml/elements.py b/pyvo/utils/xml/elements.py
index f12b1f9..53167c0 100644
--- a/pyvo/utils/xml/elements.py
+++ b/pyvo/utils/xml/elements.py
@@ -96,6 +96,7 @@ class xmlelement(property):
     """
 
     """
+
     def __init__(
         self, fget=None, fset=None, fdel=None, fadd=None, fformat=None,
         doc=None, name=None, ns=None, plain=False, cls=None, multiple_exc=None
@@ -291,6 +292,7 @@ class Element:
     Subclasses and Mixins must initialize their independent attributes after
     calling ``super().__init__``.
     """
+
     def __init__(self, config=None, pos=None, _name='', _ns='', **kwargs):
         if config is None:
             config = {}
@@ -399,10 +401,10 @@ class ElementWithXSIType(Element):
         # really needs to be fixed when we switch to namespace-aware
         # parsing.
         for name, val in kwargs.items():
-            if name=="xsi:type":
+            if name == "xsi:type":
                 xsi_type = val
                 break
-            elif name.split(":")[-1]=="type":
+            elif name.split(":")[-1] == "type":
                 xsi_type = val
 
         if xsi_type is None:
@@ -423,6 +425,7 @@ class ContentMixin(Element):
     """
     Mixin class for elements with inner content.
     """
+
     def __init__(self, config=None, pos=None, _name=None, _ns=None, **kwargs):
         super().__init__(config, pos, _name, _ns, **kwargs)
         self._content = None
diff --git a/pyvo/utils/xml/tests/test_elements.py b/pyvo/utils/xml/tests/test_elements.py
index c18dbd3..3002f3c 100644
--- a/pyvo/utils/xml/tests/test_elements.py
+++ b/pyvo/utils/xml/tests/test_elements.py
@@ -6,7 +6,6 @@ Tests for pyvo.utils.xml.elements
 
 import io
 
-import pytest
 from astropy.utils.xml import iterparser
 
 from pyvo.utils.xml import elements
@@ -58,33 +57,33 @@ class TestXSIType:
 
     def test_prefixed_type(self):
         found_type = self._parse_string(b'<tbase xsi:type="foo:TOther1"/>'
-            ).tbase.__class__
+                                        ).tbase.__class__
         assert found_type.__name__ == "TOther1"
 
     def test_unprefixed_type(self):
         # This is undesired behaviour; this test should fail once
         # we've properly parsing XML
         found_type = self._parse_string(b'<tbase xsi:type="TOther1"/>'
-            ).tbase.__class__
+                                        ).tbase.__class__
         assert found_type.__name__ == "TOther1"
 
     def test_badprefixed_type(self):
         found_type = self._parse_string(b'<tbase xsi:type="ns1:TOther2"/>'
-            ).tbase.__class__
+                                        ).tbase.__class__
         assert found_type.__name__ == "TOther2"
 
     def test_xsi_ignorable(self):
         # This is again unwelcome behaviour, but unavoidable as long
         # as we hack around namespaces
         found_type = self._parse_string(b'<tbase type="ns1:TOther2"/>'
-            ).tbase.__class__
+                                        ).tbase.__class__
         assert found_type.__name__ == "TOther2"
 
     def test_xsi_preferred(self):
         # Another piece unwelcome behaviour.
         found_type = self._parse_string(
             b'<tbase foo:type="TOther1" xsi:type="ns1:TOther2"/>'
-            ).tbase.__class__
+        ).tbase.__class__
         assert found_type.__name__ == "TOther2"
 
     def test_bad_type(self, recwarn):
diff --git a/setup.cfg b/setup.cfg
index 1092cf4..21d3c4a 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -18,13 +18,15 @@ filterwarnings =
 
 [flake8]
 max-line-length = 110
-max-doc-length = 79
-exclude = __init__.py, setup_package.py, conf.py, setup.py, version.py, conftest.py
+max-doc-length = 110
+exclude = __init__.py, conf.py, setup.py, version.py, conftest.py
+# W503 line break before operator
+ignore = W503
+
 
 [pycodestyle]
 max-line-length = 110
-max-doc-length = 79
-exclude = extern,sphinx,*parsetab.py
+max-doc-length = 110
 
 [metadata]
 name = pyvo
diff --git a/tox.ini b/tox.ini
index 3975c10..2352db8 100644
--- a/tox.ini
+++ b/tox.ini
@@ -62,34 +62,8 @@ commands =
     sphinx-build -W -b html . _build/html
 
 [testenv:codestyle]
-# We list the warnings/errors to check for here rather than in setup.cfg because
-# we don't want these options to apply whenever anyone calls flake8 from the
-# command-line or their code editor - in this case all warnings/errors should be
-# checked for. The warnings/errors we check for here are:
-# E101 - mix of tabs and spaces
-# W191 - use of tabs
-# W291 - trailing whitespace
-# W292 - no newline at end of file
-# W293 - trailing whitespace
-# W391 - blank line at end of file
-# E111 - 4 spaces per indentation level
-# E112 - 4 spaces per indentation level
-# E113 - 4 spaces per indentation level
-# E301 - expected 1 blank line, found 0
-# E302 - expected 2 blank lines, found 0
-# E303 - too many blank lines (3)
-# E304 - blank lines found after function decorator
-# E305 - expected 2 blank lines after class or function definition
-# E306 - expected 1 blank line before a nested definition
-# E502 - the backslash is redundant between brackets
-# E722 - do not use bare except
-# E901 - SyntaxError or IndentationError
-# E902 - IOError
-# E999: SyntaxError -- failed to compile a file into an Abstract Syntax Tree
-# F822: undefined name in __all__
-# F823: local variable name referenced before assignment
 skip_install = true
-description = check code style, e.g. with flake8
+description = check code style
 deps = flake8
 changedir = {toxinidir}
-commands = flake8 pyvo --count --select=E101,W191,W291,W292,W293,W391,E111,E112,E113,E30,E502,E722,E901,E902,E999,F822,F823
+commands = flake8 pyvo --count
['pyvo/samp.py', 'pyvo/utils/tests/test_prototype.py', 'pyvo/dal/dbapi2.py', 'pyvo/dal/sia2.py', 'pyvo/dal/query.py', 'pyvo/registry/rtcons.py', 'pyvo/dal/tests/test_sia2.py', 'pyvo/dal/tests/test_params.py', 'setup.cfg', 'pyvo/registry/tests/commonfixtures.py', 'pyvo/dal/params.py', 'pyvo/dal/tests/test_tap.py', 'pyvo/utils/protofeature.py', 'pyvo/dal/adhoc.py', 'pyvo/io/vosi/exceptions.py', 'pyvo/dal/tests/test_sia2_remote.py', 'tox.ini', 'pyvo/io/vosi/vodataservice.py', 'pyvo/io/vosi/tests/test_capabilities.py', 'pyvo/utils/xml/tests/test_elements.py', 'pyvo/utils/tests/test_vocabularies_remote.py', 'pyvo/utils/prototype.py', 'pyvo/utils/formatting.py', 'pyvo/utils/vocabularies.py', 'MANIFEST.in', 'pyvo/utils/xml/elements.py', 'pyvo/io/vosi/tests/test_tables.py', 'pyvo/registry/regtap.py', 'pyvo/registry/tests/test_rtcons.py', 'pyvo/utils/tests/test_http.py', 'pyvo/registry/tests/test_regtap.py', 'pyvo/dal/tests/test_mimetype.py', 'pyvo/dal/tests/test_datalink.py', 'pyvo/dal/tests/test_adhoc.py']