From 595af10688a3317f276af1123dfae91397124d5c Mon Sep 17 00:00:00 2001 From: Will Schlitzer Date: Fri, 13 Feb 2026 21:19:22 -0500 Subject: [PATCH 1/6] Add input validation and testing for geometry parameters in project.py Add input validation for 'endpoint', 'pole', and 'azimuth' to check for only one paramter being passed. Add testing to check that appropriate error is raised. --- pygmt/src/project.py | 12 +++++++++++- pygmt/tests/test_project.py | 37 ++++++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/pygmt/src/project.py b/pygmt/src/project.py index 0b5199b2647..d2372ccb7b8 100644 --- a/pygmt/src/project.py +++ b/pygmt/src/project.py @@ -10,7 +10,7 @@ from pygmt._typing import PathLike, TableLike from pygmt.alias import Alias, AliasSystem from pygmt.clib import Session -from pygmt.exceptions import GMTParameterError +from pygmt.exceptions import GMTInvalidInput, GMTParameterError from pygmt.helpers import ( build_arg_list, fmt_docstring, @@ -229,6 +229,16 @@ def project( # noqa: PLR0913 if kwargs.get("G") is not None and kwargs.get("F") is not None: raise GMTParameterError(at_most_one=["convention", "generate"]) + # Input validation for only one geometry parameter + geometry_params = [ + kwargs.get("A") is not None, + kwargs.get("E", endpoint) is not None, + kwargs.get("T", pole) is not None, + ] + if sum(geometry_params) > 1: + msg = "Must specify only one of 'azimuth', 'endpoint', or 'pole'." + raise GMTInvalidInput(msg) + output_type = validate_output_table_type(output_type, outfile=outfile) column_names = None diff --git a/pygmt/tests/test_project.py b/pygmt/tests/test_project.py index f6580aa6fa5..f1c28f4da6f 100644 --- a/pygmt/tests/test_project.py +++ b/pygmt/tests/test_project.py @@ -10,7 +10,7 @@ import pytest import xarray as xr from pygmt import project -from pygmt.exceptions import GMTParameterError +from pygmt.exceptions import GMTInvalidInput, GMTParameterError from pygmt.helpers import GMTTempFile @@ -90,3 +90,38 @@ def test_project_incorrect_parameters(): with pytest.raises(GMTParameterError): # Using `generate` with `convention` project(center=[0, -1], generate=0.5, convention="xypqrsz") + + +@pytest.mark.parametrize( + ("kwargs"), + [ + { + "center": [0, -1], + "generate": 0.5, + "data": [[0, 0]], + "azimuth": 45, + "endpoint": [0, 1], + }, + { + "center": [0, -1], + "generate": 0.5, + "data": [[0, 0]], + "azimuth": 45, + "pole": [0, 90], + }, + { + "center": [0, -1], + "generate": 0.5, + "data": [[0, 0]], + "endpoint": [0, 1], + "pole": [0, 90], + }, + ], +) +def test_project_geometry_definition_validation(kwargs): + """ + Validate input validation for mutually + exclusive projection geometry parameters. + """ + with pytest.raises(GMTInvalidInput): + project(**kwargs) From e978a2096ff60cb732963b3b3ead2e7ba40efcb3 Mon Sep 17 00:00:00 2001 From: Will Schlitzer Date: Fri, 13 Feb 2026 21:25:48 -0500 Subject: [PATCH 2/6] Fix double brackets --- pygmt/tests/test_project.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pygmt/tests/test_project.py b/pygmt/tests/test_project.py index f1c28f4da6f..4399bbeffab 100644 --- a/pygmt/tests/test_project.py +++ b/pygmt/tests/test_project.py @@ -98,21 +98,21 @@ def test_project_incorrect_parameters(): { "center": [0, -1], "generate": 0.5, - "data": [[0, 0]], + "data": [0, 0], "azimuth": 45, "endpoint": [0, 1], }, { "center": [0, -1], "generate": 0.5, - "data": [[0, 0]], + "data": [0, 0], "azimuth": 45, "pole": [0, 90], }, { "center": [0, -1], "generate": 0.5, - "data": [[0, 0]], + "data": [0, 0], "endpoint": [0, 1], "pole": [0, 90], }, From 320664e75ba7f843b60773e030e0dafc3275dc67 Mon Sep 17 00:00:00 2001 From: Will Schlitzer Date: Fri, 13 Feb 2026 21:28:14 -0500 Subject: [PATCH 3/6] Remove trailing white space --- pygmt/src/project.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pygmt/src/project.py b/pygmt/src/project.py index d2372ccb7b8..503e84bfe71 100644 --- a/pygmt/src/project.py +++ b/pygmt/src/project.py @@ -231,9 +231,9 @@ def project( # noqa: PLR0913 # Input validation for only one geometry parameter geometry_params = [ - kwargs.get("A") is not None, - kwargs.get("E", endpoint) is not None, - kwargs.get("T", pole) is not None, + kwargs.get("A") is not None, + kwargs.get("E", endpoint) is not None, + kwargs.get("T", pole) is not None, ] if sum(geometry_params) > 1: msg = "Must specify only one of 'azimuth', 'endpoint', or 'pole'." From 4de1f58f709586707a987fc33b12e1db27313fe1 Mon Sep 17 00:00:00 2001 From: Will Schlitzer Date: Sat, 14 Feb 2026 20:56:40 -0500 Subject: [PATCH 4/6] Update pygmt/src/project.py Co-authored-by: Dongdong Tian --- pygmt/src/project.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pygmt/src/project.py b/pygmt/src/project.py index 503e84bfe71..53bae05261b 100644 --- a/pygmt/src/project.py +++ b/pygmt/src/project.py @@ -236,8 +236,7 @@ def project( # noqa: PLR0913 kwargs.get("T", pole) is not None, ] if sum(geometry_params) > 1: - msg = "Must specify only one of 'azimuth', 'endpoint', or 'pole'." - raise GMTInvalidInput(msg) + raise GMTParameterError(at_most_one=["azimuth", "endpoint", "pole"]) output_type = validate_output_table_type(output_type, outfile=outfile) From 7b3ade65759426e205bd2759bc3d6725b04bd3ea Mon Sep 17 00:00:00 2001 From: Will Schlitzer Date: Sat, 14 Feb 2026 21:05:58 -0500 Subject: [PATCH 5/6] Remove parametrized test --- pygmt/tests/test_project.py | 38 +++++++++---------------------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/pygmt/tests/test_project.py b/pygmt/tests/test_project.py index 4399bbeffab..084cb0662ba 100644 --- a/pygmt/tests/test_project.py +++ b/pygmt/tests/test_project.py @@ -92,36 +92,16 @@ def test_project_incorrect_parameters(): project(center=[0, -1], generate=0.5, convention="xypqrsz") -@pytest.mark.parametrize( - ("kwargs"), - [ - { - "center": [0, -1], - "generate": 0.5, - "data": [0, 0], - "azimuth": 45, - "endpoint": [0, 1], - }, - { - "center": [0, -1], - "generate": 0.5, - "data": [0, 0], - "azimuth": 45, - "pole": [0, 90], - }, - { - "center": [0, -1], - "generate": 0.5, - "data": [0, 0], - "endpoint": [0, 1], - "pole": [0, 90], - }, - ], -) -def test_project_geometry_definition_validation(kwargs): +def test_project_geometry_definition_validation(dataframe): """ Validate input validation for mutually exclusive projection geometry parameters. """ - with pytest.raises(GMTInvalidInput): - project(**kwargs) + with pytest.raises(GMTParameterError): + project(center= [0, -1], + generate= 0.5, + data=dataframe, + endpoint=[0, 1], + azimuth=45, + pole=[0, 90],) + From c511e4d4a5437d1d2df0ea840d0dbed175213a21 Mon Sep 17 00:00:00 2001 From: actions-bot <58130806+actions-bot@users.noreply.github.com> Date: Sun, 15 Feb 2026 02:10:07 +0000 Subject: [PATCH 6/6] [format-command] fixes --- pygmt/src/project.py | 2 +- pygmt/tests/test_project.py | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/pygmt/src/project.py b/pygmt/src/project.py index 53bae05261b..bd9ffe73e93 100644 --- a/pygmt/src/project.py +++ b/pygmt/src/project.py @@ -10,7 +10,7 @@ from pygmt._typing import PathLike, TableLike from pygmt.alias import Alias, AliasSystem from pygmt.clib import Session -from pygmt.exceptions import GMTInvalidInput, GMTParameterError +from pygmt.exceptions import GMTParameterError from pygmt.helpers import ( build_arg_list, fmt_docstring, diff --git a/pygmt/tests/test_project.py b/pygmt/tests/test_project.py index 084cb0662ba..67ba45603db 100644 --- a/pygmt/tests/test_project.py +++ b/pygmt/tests/test_project.py @@ -10,7 +10,7 @@ import pytest import xarray as xr from pygmt import project -from pygmt.exceptions import GMTInvalidInput, GMTParameterError +from pygmt.exceptions import GMTParameterError from pygmt.helpers import GMTTempFile @@ -98,10 +98,11 @@ def test_project_geometry_definition_validation(dataframe): exclusive projection geometry parameters. """ with pytest.raises(GMTParameterError): - project(center= [0, -1], - generate= 0.5, + project( + center=[0, -1], + generate=0.5, data=dataframe, endpoint=[0, 1], azimuth=45, - pole=[0, 90],) - + pole=[0, 90], + )