From 85a72424c2f15e976d98c5428dde2282cc356b76 Mon Sep 17 00:00:00 2001 From: snowman2 Date: Fri, 2 Aug 2024 23:39:33 -0500 Subject: [PATCH] ENH: Add runtime & compiled PROJ versions --- .pylintrc | 1 + docs/history.rst | 1 + pyproj/__init__.py | 12 +++++++++--- pyproj/_show_versions.py | 3 ++- pyproj/_transformer.pyi | 3 --- pyproj/_transformer.pyx | 3 --- pyproj/_version.pyi | 4 ++++ pyproj/_version.pyx | 7 +++++++ pyproj/proj.pxi | 14 ++++++++++++++ pyproj/transformer.py | 1 - setup.py | 1 + test/test_cli.py | 3 ++- test/test_show_versions.py | 6 ++++-- 13 files changed, 45 insertions(+), 14 deletions(-) create mode 100644 pyproj/_version.pyi create mode 100644 pyproj/_version.pyx diff --git a/.pylintrc b/.pylintrc index 5d546c9fa..090a520fc 100644 --- a/.pylintrc +++ b/.pylintrc @@ -9,6 +9,7 @@ extension-pkg-whitelist=pyproj._crs, pyproj._geod, pyproj._context, pyproj._compat, + pyproj._version, pyproj.database, pyproj.list diff --git a/docs/history.rst b/docs/history.rst index 8f432d473..08099d6bf 100644 --- a/docs/history.rst +++ b/docs/history.rst @@ -8,6 +8,7 @@ Latest - DEP: Minimum PROJ version 9.2 (pull #1394) - ENH: Add :meth:`CRS.is_deprecated` and :meth:`CRS.get_non_deprecated` (pull #1383) - PERF: thread local context (issue #1133) +- ENH: Add runtime & compiled PROJ versions (discussion #1420) 3.6.1 ------ diff --git a/pyproj/__init__.py b/pyproj/__init__.py index 95ac2f46b..d448b8423 100644 --- a/pyproj/__init__.py +++ b/pyproj/__init__.py @@ -38,6 +38,12 @@ from pyproj._show_versions import ( # noqa: F401 pylint: disable=unused-import show_versions, ) +from pyproj._version import ( # noqa: F401 pylint: disable=unused-import + PROJ_COMPILED_VERSION, + PROJ_COMPILED_VERSION_STR, + PROJ_VERSION, + PROJ_VERSION_STR, +) from pyproj.crs import CRS # noqa: F401 pylint: disable=unused-import from pyproj.database import ( # noqa: F401 pylint: disable=unused-import get_authorities, @@ -62,7 +68,6 @@ from pyproj.transformer import ( # noqa: F401 pylint: disable=unused-import Transformer, itransform, - proj_version_str, transform, ) @@ -82,8 +87,9 @@ "get_units_map", "show_versions", ] -__proj_version__ = proj_version_str - +__proj_version__ = PROJ_VERSION_STR +proj_version_str = PROJ_VERSION_STR # pylint: disable=invalid-name +__proj_compiled_version__ = PROJ_COMPILED_VERSION_STR try: pyproj.network.set_ca_bundle_path() except DataDirError as err: diff --git a/pyproj/_show_versions.py b/pyproj/_show_versions.py index 13cb9f589..1fe3a7f3c 100644 --- a/pyproj/_show_versions.py +++ b/pyproj/_show_versions.py @@ -46,7 +46,8 @@ def _get_proj_info(): blob = [ ("pyproj", pyproj.__version__), - ("PROJ", pyproj.__proj_version__), + ("PROJ (runtime)", pyproj.__proj_version__), + ("PROJ (compiled)", pyproj.__proj_compiled_version__), ("data dir", data_dir), ("user_data_dir", pyproj.datadir.get_user_data_dir()), ("PROJ DATA (recommended version)", get_database_metadata("PROJ_DATA.VERSION")), diff --git a/pyproj/_transformer.pyi b/pyproj/_transformer.pyi index 5a90b6e2b..21d5960e0 100644 --- a/pyproj/_transformer.pyi +++ b/pyproj/_transformer.pyi @@ -5,9 +5,6 @@ from typing import Any, NamedTuple from pyproj._crs import _CRS, AreaOfUse, Base, CoordinateOperation from pyproj.enums import ProjVersion, TransformDirection -proj_version_str: str -PROJ_VERSION: tuple[int, int, int] - class AreaOfInterest(NamedTuple): west_lon_degree: float south_lat_degree: float diff --git a/pyproj/_transformer.pyx b/pyproj/_transformer.pyx index 87d7b71c2..149e4d701 100644 --- a/pyproj/_transformer.pyx +++ b/pyproj/_transformer.pyx @@ -25,9 +25,6 @@ from pyproj.aoi import AreaOfInterest from pyproj.enums import ProjVersion, TransformDirection, WktVersion from pyproj.exceptions import ProjError -# version number string for PROJ -proj_version_str = f"{PROJ_VERSION_MAJOR}.{PROJ_VERSION_MINOR}.{PROJ_VERSION_PATCH}" -PROJ_VERSION = (PROJ_VERSION_MAJOR, PROJ_VERSION_MINOR, PROJ_VERSION_PATCH) _AUTH_CODE_RE = re.compile(r"(?P\w+)\:(?P\w+)") diff --git a/pyproj/_version.pyi b/pyproj/_version.pyi new file mode 100644 index 000000000..e540549f5 --- /dev/null +++ b/pyproj/_version.pyi @@ -0,0 +1,4 @@ +PROJ_VERSION: tuple[int, int, int] +PROJ_VERSION_STR: str +PROJ_COMPILED_VERSION: tuple[int, int, int] +PROJ_COMPILED_VERSION_STR: str diff --git a/pyproj/_version.pyx b/pyproj/_version.pyx new file mode 100644 index 000000000..58523a524 --- /dev/null +++ b/pyproj/_version.pyx @@ -0,0 +1,7 @@ +include "proj.pxi" + +cdef PJ_INFO _PROJ_INFO = proj_info() +PROJ_VERSION = (_PROJ_INFO.major, _PROJ_INFO.minor, _PROJ_INFO.patch) +PROJ_VERSION_STR = f"{_PROJ_INFO.major}.{_PROJ_INFO.minor}.{_PROJ_INFO.patch}" +PROJ_COMPILED_VERSION = (PROJ_VERSION_MAJOR, PROJ_VERSION_MINOR, PROJ_VERSION_PATCH) +PROJ_COMPILED_VERSION_STR = f"{PROJ_VERSION_MAJOR}.{PROJ_VERSION_MINOR}.{PROJ_VERSION_PATCH}" diff --git a/pyproj/proj.pxi b/pyproj/proj.pxi index cc42ad42b..d4db59d80 100644 --- a/pyproj/proj.pxi +++ b/pyproj/proj.pxi @@ -35,6 +35,20 @@ cdef extern from "proj.h" nogil: PJ *proj_create (PJ_CONTEXT *ctx, const char *definition) PJ *proj_normalize_for_visualization(PJ_CONTEXT *ctx, const PJ* obj) + ctypedef struct PJ_INFO: + int major # Major release number + int minor # Minor release number + int patch # Patch level + const char *release # Release info. Version + date + const char *version # Full version number + const char *searchpath # Paths where init and grid files are + # looked for. Paths are separated by + # semi-colons on Windows, and colons + # on non-Windows platforms. + const char *const *paths + size_t path_count + PJ_INFO proj_info() + ctypedef struct PJ_PROJ_INFO: const char *id const char *description diff --git a/pyproj/transformer.py b/pyproj/transformer.py index ffa680c89..e3d0775e2 100644 --- a/pyproj/transformer.py +++ b/pyproj/transformer.py @@ -27,7 +27,6 @@ AreaOfInterest, _Transformer, _TransformerGroup, - proj_version_str, ) from pyproj.datadir import get_user_data_dir from pyproj.enums import ProjVersion, TransformDirection, WktVersion diff --git a/setup.py b/setup.py index d99717d96..9987cff5e 100644 --- a/setup.py +++ b/setup.py @@ -212,6 +212,7 @@ def get_extension_modules(): Extension("pyproj.list", ["pyproj/list.pyx"], **ext_options), Extension("pyproj._network", ["pyproj/_network.pyx"], **ext_options), Extension("pyproj._sync", ["pyproj/_sync.pyx"], **ext_options), + Extension("pyproj._version", ["pyproj/_version.pyx"], **ext_options), ], quiet=True, compile_time_env={ diff --git a/test/test_cli.py b/test/test_cli.py index 7a696de75..4f249ba3d 100644 --- a/test/test_cli.py +++ b/test/test_cli.py @@ -39,7 +39,8 @@ def test_main__verbose(input_command, option, tmpdir): input_command + [option], stderr=subprocess.STDOUT ).decode("utf-8") assert "pyproj:" in output - assert "PROJ:" in output + assert "PROJ (compiled):" in output + assert "PROJ (runtime):" in output assert "data dir" in output assert "user_data_dir" in output assert "System" in output diff --git a/test/test_show_versions.py b/test/test_show_versions.py index 353fae175..841cf948f 100644 --- a/test/test_show_versions.py +++ b/test/test_show_versions.py @@ -9,7 +9,8 @@ def test_get_proj_info(): pyproj_info = _get_proj_info() assert "pyproj" in pyproj_info - assert "PROJ" in pyproj_info + assert "PROJ (runtime)" in pyproj_info + assert "PROJ (compiled)" in pyproj_info assert "data dir" in pyproj_info assert "user_data_dir" in pyproj_info assert "PROJ DATA (recommended version)" in pyproj_info @@ -41,6 +42,7 @@ def test_show_versions_with_proj(capsys): out, err = capsys.readouterr() assert "System" in out assert "python" in out - assert "PROJ" in out + assert "PROJ (runtime)" in out + assert "PROJ (compiled)" in out assert "data dir" in out assert "Python deps" in out