diff --git a/pygmt/helpers/decorators.py b/pygmt/helpers/decorators.py index 529e8047dd6..94917a5fa61 100644 --- a/pygmt/helpers/decorators.py +++ b/pygmt/helpers/decorators.py @@ -12,7 +12,7 @@ from inspect import Parameter, signature import numpy as np -from pygmt.exceptions import GMTInvalidInput, GMTValueError +from pygmt.exceptions import GMTInvalidInput, GMTParameterError, GMTValueError from pygmt.helpers.utils import is_nonstr_iter COMMON_DOCSTRINGS = { @@ -534,8 +534,7 @@ def use_alias(**aliases): >>> my_module(region="bla", projection="meh", J="bla") Traceback (most recent call last): ... - pygmt.exceptions.GMTInvalidInput: - Parameters in short-form (J) and long-form (projection) can't coexist. + pygmt.exceptions.GMTParameterError: Mutually exclusive parameters: ... """ def alias_decorator(module_func): @@ -550,11 +549,10 @@ def new_module(*args, **kwargs): """ for short_param, long_alias in aliases.items(): if long_alias in kwargs and short_param in kwargs: - msg = ( - f"Parameters in short-form ({short_param}) and " - f"long-form ({long_alias}) can't coexist." + raise GMTParameterError( + at_most_one={long_alias, short_param}, + reason=f"Long-form parameter {long_alias!r} is recommended.", ) - raise GMTInvalidInput(msg) if long_alias in kwargs: kwargs[short_param] = kwargs.pop(long_alias) elif short_param in kwargs: @@ -802,9 +800,9 @@ def deprecate_parameter(oldname, newname, deprecate_version, remove_version): ... assert issubclass(w[i].category, FutureWarning) ... assert "deprecated" in str(w[i].message) data=table.txt, size=5.0, color=red - >>> # using both old and new names will raise an GMTInvalidInput exception + >>> # using both old and new names will raise an GMTParameterError exception >>> import pytest - >>> with pytest.raises(GMTInvalidInput): + >>> with pytest.raises(GMTParameterError): ... module(data="table.txt", size=5.0, sizes=4.0) """ @@ -821,8 +819,10 @@ def new_module(*args, **kwargs): """ if oldname in kwargs: if newname in kwargs: - msg = f"Can't provide both '{newname}' and '{oldname}'." - raise GMTInvalidInput(msg) + raise GMTParameterError( + at_most_one={newname, oldname}, + reason=f"{oldname!r} is deprecated and {newname!r} is recommended.", + ) msg = ( f"The '{oldname}' parameter has been deprecated since {deprecate_version}" f" and will be removed in {remove_version}." diff --git a/pygmt/src/project.py b/pygmt/src/project.py index 2dc069b644a..8f1be185843 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, @@ -227,8 +227,7 @@ def project( # noqa: PLR0913 required="data", reason="Required unless 'generate' is set." ) if kwargs.get("G") is not None and kwargs.get("F") is not None: - msg = "The 'convention' parameter is not allowed with 'generate'." - raise GMTInvalidInput(msg) + raise GMTParameterError(at_most_one={"convention", "generate"}) output_type = validate_output_table_type(output_type, outfile=outfile) diff --git a/pygmt/src/text.py b/pygmt/src/text.py index 7f3f2b2b9c8..3db86139266 100644 --- a/pygmt/src/text.py +++ b/pygmt/src/text.py @@ -9,7 +9,7 @@ from pygmt._typing import AnchorCode, PathLike, StringArrayTypes, TableLike from pygmt.alias import Alias, AliasSystem from pygmt.clib import Session -from pygmt.exceptions import GMTInvalidInput, GMTParameterError, GMTTypeError +from pygmt.exceptions import GMTParameterError, GMTTypeError from pygmt.helpers import ( _check_encoding, build_arg_list, @@ -34,7 +34,7 @@ it="use_word", w="wrap", ) -def text_( # noqa: PLR0912, PLR0913, PLR0915 +def text_( # noqa: PLR0912, PLR0913 self, textfiles: PathLike | TableLike | None = None, x=None, @@ -191,8 +191,7 @@ def text_( # noqa: PLR0912, PLR0913, PLR0915 + (position is not None) + (x is not None or y is not None) ) != 1: - msg = "Provide either 'textfiles', 'x'/'y'/'text', or 'position'/'text'." - raise GMTInvalidInput(msg) + raise GMTParameterError(at_most_one={"textfiles", "position/text", "x/y/text"}) data_is_required = position is None kind = data_kind(textfiles, required=data_is_required) @@ -209,8 +208,7 @@ def text_( # noqa: PLR0912, PLR0913, PLR0915 ) if textfiles is not None and text is not None: - msg = "'text' can't be specified when 'textfiles' is given." - raise GMTInvalidInput(msg) + raise GMTParameterError(at_most_one={"text", "textfiles"}) if kind == "empty" and text is None: raise GMTParameterError( required="text", reason="Required when 'x' and 'y' are set." diff --git a/pygmt/tests/test_project.py b/pygmt/tests/test_project.py index cdf71a236f5..f6580aa6fa5 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 @@ -87,6 +87,6 @@ def test_project_incorrect_parameters(): with pytest.raises(GMTParameterError): # No `data` or `generate` project(center=[0, -1], azimuth=45, flat_earth=True) - with pytest.raises(GMTInvalidInput): + with pytest.raises(GMTParameterError): # Using `generate` with `convention` project(center=[0, -1], generate=0.5, convention="xypqrsz") diff --git a/pygmt/tests/test_text.py b/pygmt/tests/test_text.py index a3fcdf05b0f..d871b223f22 100644 --- a/pygmt/tests/test_text.py +++ b/pygmt/tests/test_text.py @@ -7,12 +7,7 @@ import numpy as np import pytest from pygmt import Figure, config -from pygmt.exceptions import ( - GMTCLibError, - GMTInvalidInput, - GMTParameterError, - GMTTypeError, -) +from pygmt.exceptions import GMTCLibError, GMTParameterError, GMTTypeError from pygmt.helpers import GMTTempFile from pygmt.helpers.testing import skip_if_no @@ -151,11 +146,11 @@ def test_text_invalid_inputs(region): Run text by providing invalid combinations of inputs. """ fig = Figure() - with pytest.raises(GMTInvalidInput): + with pytest.raises(GMTParameterError): fig.text( region=region, projection="x1c", x=1.2, y=2.4, position="MC", text="text" ) - with pytest.raises(GMTInvalidInput): + with pytest.raises(GMTParameterError): fig.text(region=region, projection="x1c", textfiles="file.txt", text="text") with pytest.raises(GMTParameterError): fig.text(region=region, projection="x1c", position="MC", text=None) @@ -163,7 +158,7 @@ def test_text_invalid_inputs(region): fig.text( region=region, projection="x1c", position="MC", text=["text1", "text2"] ) - with pytest.raises(GMTInvalidInput): + with pytest.raises(GMTParameterError): fig.text(region=region, projection="x1c", textfiles="file.txt", x=1.2, y=2.4)