From 9b8be27482db56aa0a082672d587e0295a0f39e5 Mon Sep 17 00:00:00 2001 From: Javier Jimenez Shaw Date: Mon, 26 Feb 2024 17:21:18 +0100 Subject: [PATCH 1/6] add is_deprecated and get_non_deprecated() to CRS --- pyproj/_crs.pyi | 3 +++ pyproj/_crs.pyx | 57 ++++++++++++++++++++++++++++++++++++++++++++ pyproj/crs/crs.py | 25 +++++++++++++++++++ pyproj/proj.pxi | 3 +++ test/crs/test_crs.py | 30 +++++++++++++++++++++++ 5 files changed, 118 insertions(+) diff --git a/pyproj/_crs.pyi b/pyproj/_crs.pyi index 7d3bafdb..b46618de 100644 --- a/pyproj/_crs.pyi +++ b/pyproj/_crs.pyi @@ -235,6 +235,9 @@ class _CRS(Base): @property def is_geocentric(self) -> bool: ... def equals(self, other: Any, ignore_axis_order: bool) -> bool: ... + @property + def is_deprecated(self) -> bool: ... + def get_non_deprecated(self) -> list["_CRS"]: ... def is_proj(proj_string: str) -> bool: ... def is_wkt(proj_string: str) -> bool: ... diff --git a/pyproj/_crs.pyx b/pyproj/_crs.pyx index f6ea3b00..60e54947 100644 --- a/pyproj/_crs.pyx +++ b/pyproj/_crs.pyx @@ -3203,3 +3203,60 @@ cdef class _CRS(Base): if not isinstance(other, _CRS): return False return self._equals(other, ignore_axis_order=ignore_axis_order) + + @property + def is_deprecated(self): + """ + .. versionadded:: 3.6.2 + + Check if the CRS is deprecated + + Returns + ------- + bool + """ + return bool(proj_is_deprecated(self.projobj)) + + def get_non_deprecated(self): + """ + .. versionadded:: 3.6.2 + + Return a list of non-deprecated objects related to this. + + Returns + ------- + list[_CRS] + """ + + non_deprecated = [] + + cdef PJ_OBJ_LIST *proj_list = NULL + cdef int num_proj_objects = 0 + + proj_list = proj_get_non_deprecated( + self.context, + self.projobj + ) + if proj_list != NULL: + num_proj_objects = proj_list_get_count(proj_list) + + cdef PJ* proj = NULL + try: + for iii in range(num_proj_objects): + proj = proj_list_get(self.context, proj_list, iii) + non_deprecated.append(_CRS(_to_wkt( + self.context, + proj, + version=WktVersion.WKT2_2019, + pretty=False, + ))) + proj_destroy(proj) + proj = NULL + finally: + # If there was an error we have to call proj_destroy + # If there was none, calling it on NULL does nothing + proj_destroy(proj) + proj_list_destroy(proj_list) + _clear_proj_error() + + return non_deprecated diff --git a/pyproj/crs/crs.py b/pyproj/crs/crs.py index ce48a1a5..fbac7f85 100644 --- a/pyproj/crs/crs.py +++ b/pyproj/crs/crs.py @@ -1565,6 +1565,31 @@ def is_derived(self): """ return self._crs.is_derived + @property + def is_deprecated(self) -> bool: + """ + .. versionadded:: 3.6.2 + + Check if the CRS is deprecated + + Returns + ------- + bool + """ + return self._crs.is_deprecated + + def get_non_deprecated(self) -> list["CRS"]: + """ + .. versionadded:: 3.6.2 + + Return a list of non-deprecated objects related to this. + + Returns + ------- + list[CRS] + """ + return self._crs.get_non_deprecated() + def __eq__(self, other: Any) -> bool: return self.equals(other) diff --git a/pyproj/proj.pxi b/pyproj/proj.pxi index 96bab8c4..1502b337 100644 --- a/pyproj/proj.pxi +++ b/pyproj/proj.pxi @@ -546,3 +546,6 @@ cdef extern from "proj.h" nogil: ) void proj_unit_list_destroy(PROJ_UNIT_INFO** list) const char *proj_context_get_url_endpoint(PJ_CONTEXT* ctx) + + int proj_is_deprecated(const PJ *obj) + PJ_OBJ_LIST *proj_get_non_deprecated(PJ_CONTEXT *ctx, const PJ *obj) diff --git a/test/crs/test_crs.py b/test/crs/test_crs.py index d37480c0..2224897a 100644 --- a/test/crs/test_crs.py +++ b/test/crs/test_crs.py @@ -232,6 +232,36 @@ def test_to_wkt_pretty(): assert "\n" not in crs.to_wkt() +def test_no_non_deprecated(): + crs = CRS.from_epsg(4326) + assert not crs.is_deprecated + non_dep = crs.get_non_deprecated() + assert len(non_dep) == 0 + + +def test_non_deprecated(): + crs = CRS.from_epsg(28473) + assert crs.is_deprecated + non_dep = crs.get_non_deprecated() + assert len(non_dep) == 1 + assert "EPSG:2503" == ":".join(non_dep[0].to_authority()) + + +def test_non_deprecated_empty(): + crs = CRS.from_epsg(3151) + assert crs.is_deprecated + assert len(crs.get_non_deprecated()) == 0 + + +def test_non_deprecated_multiple(): + crs = CRS.from_epsg(3315) + assert crs.is_deprecated + non_dep = [":".join(el.to_authority()) for el in crs.get_non_deprecated()] + assert len(non_dep) == 4 + for elem in ["EPSG:3989", "EPSG:3988", "EPSG:3987", "EPSG:3986"]: + assert elem in non_dep + + @pytest.mark.parametrize( "version, expected", [ From 529a686d43425e9c27596c16bce697287a724661 Mon Sep 17 00:00:00 2001 From: Javier Jimenez Shaw Date: Mon, 26 Feb 2024 20:47:25 +0100 Subject: [PATCH 2/6] add line in docs/history.rst --- docs/history.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/history.rst b/docs/history.rst index 8510a1aa..34feecb6 100644 --- a/docs/history.rst +++ b/docs/history.rst @@ -4,6 +4,7 @@ Change Log Latest ------ - DEP: Minimum supported Python version 3.10 (pull #1357) +- ENH: Add :meth:`CRS.is_deprecated` and :meth:`CRS.get_non_deprecated` (pull #1383) 3.6.1 ------ From ce282fa2b19912f8a02aa1bcd1ec769cca032b99 Mon Sep 17 00:00:00 2001 From: Javier Jimenez Shaw Date: Thu, 29 Feb 2024 09:40:55 +0100 Subject: [PATCH 3/6] is_deprecated added in 3.7.0 Co-authored-by: Alan D. Snow --- pyproj/_crs.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproj/_crs.pyx b/pyproj/_crs.pyx index 60e54947..f3e0d0b1 100644 --- a/pyproj/_crs.pyx +++ b/pyproj/_crs.pyx @@ -3207,7 +3207,7 @@ cdef class _CRS(Base): @property def is_deprecated(self): """ - .. versionadded:: 3.6.2 + .. versionadded:: 3.7.0 Check if the CRS is deprecated From a188b87806ecd6055c515fc003df5e4522d1ed6b Mon Sep 17 00:00:00 2001 From: Javier Jimenez Shaw Date: Thu, 29 Feb 2024 09:41:13 +0100 Subject: [PATCH 4/6] get_non_deprecated added in 3.7.0 Co-authored-by: Alan D. Snow --- pyproj/_crs.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproj/_crs.pyx b/pyproj/_crs.pyx index f3e0d0b1..513149e1 100644 --- a/pyproj/_crs.pyx +++ b/pyproj/_crs.pyx @@ -3219,7 +3219,7 @@ cdef class _CRS(Base): def get_non_deprecated(self): """ - .. versionadded:: 3.6.2 + .. versionadded:: 3.7.0 Return a list of non-deprecated objects related to this. From 4fda999a41579ef6e8f0da01d7b276132cc51077 Mon Sep 17 00:00:00 2001 From: Javier Jimenez Shaw Date: Thu, 29 Feb 2024 09:42:45 +0100 Subject: [PATCH 5/6] is_deprecated added in 3.7.0 --- pyproj/crs/crs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproj/crs/crs.py b/pyproj/crs/crs.py index fbac7f85..7e5a8254 100644 --- a/pyproj/crs/crs.py +++ b/pyproj/crs/crs.py @@ -1568,7 +1568,7 @@ def is_derived(self): @property def is_deprecated(self) -> bool: """ - .. versionadded:: 3.6.2 + .. versionadded:: 3.7.0 Check if the CRS is deprecated From 5fda2689fa7483a7872a4ad4a429280f40806079 Mon Sep 17 00:00:00 2001 From: Javier Jimenez Shaw Date: Thu, 29 Feb 2024 09:42:56 +0100 Subject: [PATCH 6/6] get_non_deprecated added in 3.7.0 --- pyproj/crs/crs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproj/crs/crs.py b/pyproj/crs/crs.py index 7e5a8254..9436cac3 100644 --- a/pyproj/crs/crs.py +++ b/pyproj/crs/crs.py @@ -1580,7 +1580,7 @@ def is_deprecated(self) -> bool: def get_non_deprecated(self) -> list["CRS"]: """ - .. versionadded:: 3.6.2 + .. versionadded:: 3.7.0 Return a list of non-deprecated objects related to this.