diff --git a/docs/api/crs/crs.rst b/docs/api/crs/crs.rst index 496966875..9d834790b 100644 --- a/docs/api/crs/crs.rst +++ b/docs/api/crs/crs.rst @@ -74,6 +74,15 @@ CompoundCRS :special-members: __init__ +CustomConstructorCRS +------------------------ + +.. autoclass:: pyproj.crs.CustomConstructorCRS + :members: + :show-inheritance: + :special-members: __init__ + + is_wkt ----------------- diff --git a/pyproj/crs/__init__.py b/pyproj/crs/__init__.py index 584164b6f..228af4c5f 100644 --- a/pyproj/crs/__init__.py +++ b/pyproj/crs/__init__.py @@ -17,6 +17,7 @@ CRS, BoundCRS, CompoundCRS, + CustomConstructorCRS, DerivedGeographicCRS, GeocentricCRS, GeographicCRS, diff --git a/pyproj/crs/crs.py b/pyproj/crs/crs.py index b5bcfe70c..3376115a6 100644 --- a/pyproj/crs/crs.py +++ b/pyproj/crs/crs.py @@ -1535,11 +1535,10 @@ def __repr__(self) -> str: ) -class _MakerCRS(CRS): +class CustomConstructorCRS(CRS): """ - This class exists to handle the oddities to do with the - maker CRS classes having a different constructor than - the base CRS classes. + This class is a base class for CRS classes + that use a different constructor than the main CRS class. .. versionadded:: 3.2.0 @@ -1592,7 +1591,7 @@ def from_user_input(cls, value: Any, **kwargs) -> "CRS": if isinstance(value, cls): return value crs = cls.__new__(cls) - super(_MakerCRS, crs).__init__(value, **kwargs) + super(CustomConstructorCRS, crs).__init__(value, **kwargs) crs._check_type() return crs @@ -1668,7 +1667,7 @@ def to_3d(self, name: Optional[str] = None) -> "CRS": return CRS(self._crs.to_3d(name=name)) -class GeographicCRS(_MakerCRS): +class GeographicCRS(CustomConstructorCRS): """ .. versionadded:: 2.5.0 @@ -1708,7 +1707,7 @@ def __init__( super().__init__(geographic_crs_json) -class DerivedGeographicCRS(_MakerCRS): +class DerivedGeographicCRS(CustomConstructorCRS): """ .. versionadded:: 2.5.0 @@ -1764,7 +1763,7 @@ def __init__( super().__init__(derived_geographic_crs_json) -class GeocentricCRS(_MakerCRS): +class GeocentricCRS(CustomConstructorCRS): """ .. versionadded:: 3.2.0 @@ -1819,7 +1818,7 @@ def __init__( super().__init__(geocentric_crs_json) -class ProjectedCRS(_MakerCRS): +class ProjectedCRS(CustomConstructorCRS): """ .. versionadded:: 2.5.0 @@ -1868,7 +1867,7 @@ def __init__( super().__init__(proj_crs_json) -class VerticalCRS(_MakerCRS): +class VerticalCRS(CustomConstructorCRS): """ .. versionadded:: 2.5.0 @@ -1916,7 +1915,7 @@ def __init__( super().__init__(vert_crs_json) -class CompoundCRS(_MakerCRS): +class CompoundCRS(CustomConstructorCRS): """ .. versionadded:: 2.5.0 @@ -1948,7 +1947,7 @@ def __init__(self, name: str, components: List[Any]) -> None: super().__init__(compound_crs_json) -class BoundCRS(_MakerCRS): +class BoundCRS(CustomConstructorCRS): """ .. versionadded:: 2.5.0 diff --git a/test/crs/test_crs_maker.py b/test/crs/test_crs_maker.py index fb085822e..f6ea83210 100644 --- a/test/crs/test_crs_maker.py +++ b/test/crs/test_crs_maker.py @@ -4,6 +4,7 @@ CRS, BoundCRS, CompoundCRS, + CustomConstructorCRS, DerivedGeographicCRS, GeocentricCRS, GeographicCRS, @@ -321,3 +322,22 @@ def test_bound_crs_crs__from_methods(): assert_maker_inheritance_valid( BoundCRS.from_json_dict(CRS(crs_str).to_json_dict()), BoundCRS ) + + +def test_custom_constructor_crs__not_implemented(): + class MyCustomInit(CustomConstructorCRS): + def __init__(self, *, name: str): + super().__init__(name) + + with pytest.raises(NotImplementedError): + MyCustomInit.from_epsg(4326) + + +def test_custom_constructor_crs(): + class MyCustomInit(CustomConstructorCRS): + _expected_types = ("Geographic 2D CRS",) + + def __init__(self, *, name: str): + super().__init__(name) + + assert isinstance(MyCustomInit.from_epsg(4326), MyCustomInit)