diff --git a/lib/iris/coords.py b/lib/iris/coords.py index 050a6cdaad..c5af246166 100644 --- a/lib/iris/coords.py +++ b/lib/iris/coords.py @@ -8,10 +8,11 @@ """ -from abc import ABCMeta +from abc import ABCMeta, abstractmethod from collections import namedtuple from collections.abc import Iterator import copy +from functools import wraps from itertools import chain, zip_longest import operator import warnings @@ -1282,6 +1283,7 @@ class Coord(_DimensionalMetadata): """ + @abstractmethod def __init__( self, points, @@ -2565,6 +2567,10 @@ class AuxCoord(Coord): """ + @wraps(Coord.__init__, assigned=("__doc__",), updated=()) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + # Logically, :class:`Coord` is an abstract class and all actual coords must # be members of some concrete subclass, i.e. an :class:`AuxCoord` or # a :class:`DimCoord`. diff --git a/lib/iris/tests/unit/coords/test_CellMethod.py b/lib/iris/tests/unit/coords/test_CellMethod.py index da35d76096..88906dd905 100644 --- a/lib/iris/tests/unit/coords/test_CellMethod.py +++ b/lib/iris/tests/unit/coords/test_CellMethod.py @@ -12,7 +12,7 @@ import iris.tests as tests from iris._cube_coord_common import CFVariableMixin -from iris.coords import CellMethod, Coord +from iris.coords import CellMethod, AuxCoord class Test(tests.IrisTest): @@ -27,38 +27,38 @@ def _check(self, token, coord, default=False): def test_coord_standard_name(self): token = "air_temperature" - coord = Coord(1, standard_name=token) + coord = AuxCoord(1, standard_name=token) self._check(token, coord) def test_coord_long_name(self): token = "long_name" - coord = Coord(1, long_name=token) + coord = AuxCoord(1, long_name=token) self._check(token, coord) def test_coord_long_name_default(self): token = "long name" # includes space - coord = Coord(1, long_name=token) + coord = AuxCoord(1, long_name=token) self._check(token, coord, default=True) def test_coord_var_name(self): token = "var_name" - coord = Coord(1, var_name=token) + coord = AuxCoord(1, var_name=token) self._check(token, coord) def test_coord_var_name_fail(self): token = "var name" # includes space emsg = "is not a valid NetCDF variable name" with self.assertRaisesRegex(ValueError, emsg): - Coord(1, var_name=token) + AuxCoord(1, var_name=token) def test_coord_stash(self): token = "stash" - coord = Coord(1, attributes=dict(STASH=token)) + coord = AuxCoord(1, attributes=dict(STASH=token)) self._check(token, coord) def test_coord_stash_default(self): token = "_stash" # includes leading underscore - coord = Coord(1, attributes=dict(STASH=token)) + coord = AuxCoord(1, attributes=dict(STASH=token)) self._check(token, coord, default=True) def test_string(self): @@ -75,14 +75,14 @@ def test_string_default(self): def test_mixture(self): token = "air_temperature" - coord = Coord(1, standard_name=token) + coord = AuxCoord(1, standard_name=token) result = CellMethod(self.method, coords=[coord, token]) expected = "{}: {}, {}".format(self.method, token, token) self.assertEqual(str(result), expected) def test_mixture_default(self): token = "air temperature" # includes space - coord = Coord(1, long_name=token) + coord = AuxCoord(1, long_name=token) result = CellMethod(self.method, coords=[coord, token]) expected = "{}: unknown, unknown".format(self.method, token, token) self.assertEqual(str(result), expected) diff --git a/lib/iris/tests/unit/coords/test_Coord.py b/lib/iris/tests/unit/coords/test_Coord.py index b23b6daa8c..ac8a89bcd5 100644 --- a/lib/iris/tests/unit/coords/test_Coord.py +++ b/lib/iris/tests/unit/coords/test_Coord.py @@ -1010,5 +1010,15 @@ def test_remove_bounds(self): self.assertFalse(coord.climatological) +class Test_Coord_is_abstract(tests.IrisTest): + def test_instantiate_fail(self): + emsg = ( + "Can't instantiate abstract class Coord with abstract" + " methods __init__" + ) + with self.assertRaisesRegex(TypeError, emsg): + _ = Coord(points=[0, 1]) + + if __name__ == "__main__": tests.main()