From a8afa0321d13db1ed56a2bbd871761a4b2ef6c73 Mon Sep 17 00:00:00 2001 From: madhavcodez Date: Mon, 29 Jun 2026 21:36:13 -0500 Subject: [PATCH] ENH: add guess_wkt_version to return the WKT version of a string is_wkt only reports whether a string is WKT. guess_wkt_version wraps proj_context_guess_wkt_dialect and returns the matching pyproj.enums.WktVersion, or None when the string is not WKT. Closes #1031 --- docs/api/crs/crs.rst | 6 ++++++ docs/history.rst | 1 + pyproj/_crs.pyi | 1 + pyproj/_crs.pyx | 32 ++++++++++++++++++++++++++++++++ pyproj/crs/__init__.py | 2 ++ pyproj/proj.pxi | 1 + test/crs/test_crs.py | 19 +++++++++++++++++++ 7 files changed, 62 insertions(+) diff --git a/docs/api/crs/crs.rst b/docs/api/crs/crs.rst index 9d834790b..da1b35731 100644 --- a/docs/api/crs/crs.rst +++ b/docs/api/crs/crs.rst @@ -83,6 +83,12 @@ CustomConstructorCRS :special-members: __init__ +guess_wkt_version +----------------- + +.. autofunction:: pyproj.crs.guess_wkt_version + + is_wkt ----------------- diff --git a/docs/history.rst b/docs/history.rst index 43a43579a..4cc742fa0 100644 --- a/docs/history.rst +++ b/docs/history.rst @@ -3,6 +3,7 @@ Change Log Latest ------ +- ENH: Added :func:`pyproj.crs.guess_wkt_version` to return the WKT version of a string (issue #1031) - WHL: Wheels contain PROJ 9.7.1 (pull #1573) - WHL: Upgrade from MacOS 13 to MacOS 15 (X86_64) wheels (issue #1532 & #1543) - ENH: Add :meth:`database.query_geodetic_crs_from_datum` (pull #1390) diff --git a/pyproj/_crs.pyi b/pyproj/_crs.pyi index 49f979231..4a7e49f95 100644 --- a/pyproj/_crs.pyi +++ b/pyproj/_crs.pyi @@ -230,4 +230,5 @@ class _CRS(Base): def is_proj(proj_string: str) -> bool: ... def is_wkt(proj_string: str) -> bool: ... +def guess_wkt_version(proj_string: str) -> Optional[WktVersion]: ... def _load_proj_json(in_proj_json: str) -> dict: ... diff --git a/pyproj/_crs.pyx b/pyproj/_crs.pyx index e68c1ad64..bd8c10bc3 100644 --- a/pyproj/_crs.pyx +++ b/pyproj/_crs.pyx @@ -49,6 +49,38 @@ def is_wkt(str proj_string not None): return proj_context_guess_wkt_dialect(NULL, b_proj_string) != PJ_GUESSED_NOT_WKT +def guess_wkt_version(str proj_string not None): + """ + .. versionadded:: 3.8.0 + + Guess the version of the Well-Known Text format of the input string. + + Parameters + ---------- + proj_string: str + The projection string. + + Returns + ------- + Optional[pyproj.enums.WktVersion]: + The WKT version of the string or None if it is not WKT. + """ + cdef bytes b_proj_string = cstrencode(proj_string) + cdef PJ_GUESSED_WKT_DIALECT dialect = proj_context_guess_wkt_dialect( + NULL, b_proj_string + ) + # PJ_GUESSED_WKT2_2018 is the legacy alias of PJ_GUESSED_WKT2_2019. + if dialect == PJ_GUESSED_WKT2_2019: + return WktVersion.WKT2_2019 + if dialect == PJ_GUESSED_WKT2_2015: + return WktVersion.WKT2_2015 + if dialect == PJ_GUESSED_WKT1_GDAL: + return WktVersion.WKT1_GDAL + if dialect == PJ_GUESSED_WKT1_ESRI: + return WktVersion.WKT1_ESRI + return None + + def is_proj(str proj_string not None): """ .. versionadded:: 2.2.2 diff --git a/pyproj/crs/__init__.py b/pyproj/crs/__init__.py index ffbc138ee..23a52c92f 100644 --- a/pyproj/crs/__init__.py +++ b/pyproj/crs/__init__.py @@ -10,6 +10,7 @@ Datum, Ellipsoid, PrimeMeridian, + guess_wkt_version, is_proj, is_wkt, ) @@ -36,6 +37,7 @@ "GeographicCRS", "ProjectedCRS", "VerticalCRS", + "guess_wkt_version", "is_proj", "is_wkt", ] diff --git a/pyproj/proj.pxi b/pyproj/proj.pxi index bbc46eb08..7d37e4752 100644 --- a/pyproj/proj.pxi +++ b/pyproj/proj.pxi @@ -298,6 +298,7 @@ cdef extern from "proj.h" nogil: void proj_int_list_destroy(int* list) void proj_context_use_proj4_init_rules(PJ_CONTEXT *ctx, int enable) ctypedef enum PJ_GUESSED_WKT_DIALECT: + PJ_GUESSED_WKT2_2019 PJ_GUESSED_WKT2_2018 PJ_GUESSED_WKT2_2015 PJ_GUESSED_WKT1_GDAL diff --git a/test/crs/test_crs.py b/test/crs/test_crs.py index 1eefb4cc6..b039d8427 100644 --- a/test/crs/test_crs.py +++ b/test/crs/test_crs.py @@ -15,6 +15,7 @@ Datum, Ellipsoid, PrimeMeridian, + guess_wkt_version, ) from pyproj.crs.enums import CoordinateOperationType, DatumType from pyproj.enums import ProjVersion, WktVersion @@ -1000,6 +1001,24 @@ def test_to_wkt_enum__invalid(): crs.to_wkt("WKT_INVALID") +@pytest.mark.parametrize( + "wkt_version", + [ + WktVersion.WKT2_2019, + WktVersion.WKT2_2015, + WktVersion.WKT1_GDAL, + WktVersion.WKT1_ESRI, + ], +) +def test_guess_wkt_version(wkt_version): + crs = CRS.from_epsg(4326) + assert guess_wkt_version(crs.to_wkt(wkt_version)) == wkt_version + + +def test_guess_wkt_version__not_wkt(): + assert guess_wkt_version("+proj=longlat +datum=WGS84 +no_defs +type=crs") is None + + @pytest.mark.parametrize( "wkt_version", ["WKT2_2015", "WKT2_2015_SIMPLIFIED", "WKT1_GDAL", "WKT1_ESRI"],