From 0c82b3cad9c3afffd4f389653eff67f797a9f12c Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Thu, 3 Oct 2024 14:42:07 +0800 Subject: [PATCH 1/6] data_kind: Refactor the if-else statements into if-return statements --- pygmt/helpers/utils.py | 67 ++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/pygmt/helpers/utils.py b/pygmt/helpers/utils.py index 24a938df518..59928482091 100644 --- a/pygmt/helpers/utils.py +++ b/pygmt/helpers/utils.py @@ -187,7 +187,7 @@ def _check_encoding( return "ISOLatin1+" -def data_kind( +def data_kind( # noqa: PLR0911 data: Any = None, required: bool = True ) -> Literal[ "arg", "file", "geojson", "grid", "image", "matrix", "stringio", "vectors" @@ -195,15 +195,18 @@ def data_kind( r""" Check the kind of data that is provided to a module. - The ``data`` argument can be in any type, but only following types are supported: + The ``data`` argument can be in any type. Following data kinds are recognized: - - a string or a :class:`pathlib.PurePath` object or a sequence of them, representing - a file name or a list of file names - - a 2-D or 3-D :class:`xarray.DataArray` object - - a 2-D matrix - - None, bool, int or float type representing an optional arguments - - a geo-like Python object that implements ``__geo_interface__`` (e.g., - geopandas.GeoDataFrame or shapely.geometry) + - ``"arg"``: data is ``None`` and ``required=False``, or bool, int, float, + representing an optional argument, used for dealing with optional virtual files + - ``"file"``: a string or a :class:`pathlib.PurePath` object or a sequence of them, + representing one or more file names + - ``"geojson"``: a geo-like Python object that implements ``__geo_interface__`` + (e.g., geopandas.GeoDataFrame or shapely.geometry) + - ``"grid"``: a :class:`xarray.DataArray` object that is not 3-D + - ``"image"``: a 3-D :class:`xarray.DataArray` object + - ``"matrix"``: anything that is not None + - ``"vectors"``: data is ``None`` and ``required=True`` Parameters ---------- @@ -287,30 +290,36 @@ def data_kind( >>> data_kind(data=None) 'vectors' """ - kind: Literal[ - "arg", "file", "geojson", "grid", "image", "matrix", "stringio", "vectors" - ] + # One file or a list/tuple of files. if isinstance(data, str | pathlib.PurePath) or ( isinstance(data, list | tuple) and all(isinstance(_file, str | pathlib.PurePath) for _file in data) ): - # One or more files - kind = "file" - elif isinstance(data, bool | int | float) or (data is None and not required): - kind = "arg" - elif isinstance(data, io.StringIO): - kind = "stringio" - elif isinstance(data, xr.DataArray): - kind = "image" if len(data.dims) == 3 else "grid" - elif hasattr(data, "__geo_interface__"): - # geo-like Python object that implements ``__geo_interface__`` - # (geopandas.GeoDataFrame or shapely.geometry) - kind = "geojson" - elif data is not None: - kind = "matrix" - else: - kind = "vectors" - return kind + return "file" + + # A StringIO object. + if isinstance(data, io.StringIO): + return "stringio" + + # An option argument, mainly for dealing optional virtual files. + if isinstance(data, bool | int | float) or (data is None and not required): + return "arg" + + # An xarray.DataArray object, representing a grid or an image. + if isinstance(data, xr.DataArray): + return "image" if len(data.dims) == 3 else "grid" + + # Geo-like Python object that implements ``__geo_interface__`` (e.g., + # geopandas.GeoDataFrame or shapely.geometry). + # Reference: https://gist.github.com/sgillies/2217756 + if hasattr(data, "__geo_interface__"): + return "geojson" + + # Any not-None is considered as a matrix. + if data is not None: + return "matrix" + + return "vectors" def non_ascii_to_octal( From 0eb4f8fcc3b7e29d33ee4d9dad75d8edc5e5a8a8 Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Thu, 3 Oct 2024 17:27:16 +0800 Subject: [PATCH 2/6] Make 'data' a required parameter --- pygmt/helpers/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pygmt/helpers/utils.py b/pygmt/helpers/utils.py index 59928482091..0fe90a886b3 100644 --- a/pygmt/helpers/utils.py +++ b/pygmt/helpers/utils.py @@ -188,7 +188,7 @@ def _check_encoding( def data_kind( # noqa: PLR0911 - data: Any = None, required: bool = True + data: Any, required: bool = True ) -> Literal[ "arg", "file", "geojson", "grid", "image", "matrix", "stringio", "vectors" ]: From 3d8be4d5982008a58c38cfd1aa879c9f64a524e2 Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Thu, 3 Oct 2024 19:26:12 +0800 Subject: [PATCH 3/6] Add docstrings for stringio --- pygmt/helpers/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pygmt/helpers/utils.py b/pygmt/helpers/utils.py index 0fe90a886b3..4c2451762ce 100644 --- a/pygmt/helpers/utils.py +++ b/pygmt/helpers/utils.py @@ -195,7 +195,7 @@ def data_kind( # noqa: PLR0911 r""" Check the kind of data that is provided to a module. - The ``data`` argument can be in any type. Following data kinds are recognized: + The ``data`` argument can be in any types. Following data kinds are recognized: - ``"arg"``: data is ``None`` and ``required=False``, or bool, int, float, representing an optional argument, used for dealing with optional virtual files @@ -205,6 +205,7 @@ def data_kind( # noqa: PLR0911 (e.g., geopandas.GeoDataFrame or shapely.geometry) - ``"grid"``: a :class:`xarray.DataArray` object that is not 3-D - ``"image"``: a 3-D :class:`xarray.DataArray` object + - ``"stringio"``: a :class:`io.StringIO` object - ``"matrix"``: anything that is not None - ``"vectors"``: data is ``None`` and ``required=True`` From 048762a2edf55a5427dfc0135c2bde8dedd00a1b Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Mon, 7 Oct 2024 10:08:00 +0800 Subject: [PATCH 4/6] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Yvonne Fröhlich <94163266+yvonnefroehlich@users.noreply.github.com> --- pygmt/helpers/utils.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pygmt/helpers/utils.py b/pygmt/helpers/utils.py index 4c2451762ce..6b1f3f43e06 100644 --- a/pygmt/helpers/utils.py +++ b/pygmt/helpers/utils.py @@ -195,9 +195,10 @@ def data_kind( # noqa: PLR0911 r""" Check the kind of data that is provided to a module. - The ``data`` argument can be in any types. Following data kinds are recognized: + The argument passed to the ``data`` parameter can have any data type. The + following data kinds are recognized and returned as ``kind``: - - ``"arg"``: data is ``None`` and ``required=False``, or bool, int, float, + - ``"arg"``: ``data`` is ``None`` and ``required=False``, or bool, int, float, representing an optional argument, used for dealing with optional virtual files - ``"file"``: a string or a :class:`pathlib.PurePath` object or a sequence of them, representing one or more file names @@ -206,8 +207,8 @@ def data_kind( # noqa: PLR0911 - ``"grid"``: a :class:`xarray.DataArray` object that is not 3-D - ``"image"``: a 3-D :class:`xarray.DataArray` object - ``"stringio"``: a :class:`io.StringIO` object - - ``"matrix"``: anything that is not None - - ``"vectors"``: data is ``None`` and ``required=True`` + - ``"matrix"``: anything that is not ``None`` + - ``"vectors"``: ``data`` is ``None`` and ``required=True`` Parameters ---------- From 33051ac88eb7e32119500ac8880f329d01be6d83 Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Mon, 7 Oct 2024 12:32:39 +0800 Subject: [PATCH 5/6] Refactor into match-case statements --- pygmt/helpers/utils.py | 57 +++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/pygmt/helpers/utils.py b/pygmt/helpers/utils.py index 6b1f3f43e06..9f099862ec2 100644 --- a/pygmt/helpers/utils.py +++ b/pygmt/helpers/utils.py @@ -187,7 +187,7 @@ def _check_encoding( return "ISOLatin1+" -def data_kind( # noqa: PLR0911 +def data_kind( data: Any, required: bool = True ) -> Literal[ "arg", "file", "geojson", "grid", "image", "matrix", "stringio", "vectors" @@ -292,36 +292,31 @@ def data_kind( # noqa: PLR0911 >>> data_kind(data=None) 'vectors' """ - # One file or a list/tuple of files. - if isinstance(data, str | pathlib.PurePath) or ( - isinstance(data, list | tuple) - and all(isinstance(_file, str | pathlib.PurePath) for _file in data) - ): - return "file" - - # A StringIO object. - if isinstance(data, io.StringIO): - return "stringio" - - # An option argument, mainly for dealing optional virtual files. - if isinstance(data, bool | int | float) or (data is None and not required): - return "arg" - - # An xarray.DataArray object, representing a grid or an image. - if isinstance(data, xr.DataArray): - return "image" if len(data.dims) == 3 else "grid" - - # Geo-like Python object that implements ``__geo_interface__`` (e.g., - # geopandas.GeoDataFrame or shapely.geometry). - # Reference: https://gist.github.com/sgillies/2217756 - if hasattr(data, "__geo_interface__"): - return "geojson" - - # Any not-None is considered as a matrix. - if data is not None: - return "matrix" - - return "vectors" + match data: + case str() | pathlib.PurePath(): # One file. + kind = "file" + case list() | tuple() if all( + isinstance(_file, str | pathlib.PurePath) for _file in data + ): # A list/tuple of files. + kind = "file" + case io.StringIO(): + kind = "stringio" + case (bool() | int() | float()) | None if not required: + # An option argument, mainly for dealing optional virtual files. + kind = "arg" + case xr.DataArray(): + # An xarray.DataArray object, representing either a grid or an image. + kind = "image" if len(data.dims) == 3 else "grid" + case x if hasattr(x, "__geo_interface__"): + # Geo-like Python object that implements ``__geo_interface__`` (e.g., + # geopandas.GeoDataFrame or shapely.geometry). + # Reference: https://gist.github.com/sgillies/2217756 + kind = "geojson" + case x if x is not None: # Any not-None is considered as a matrix. + kind = "matrix" + case _: # Fall back to "vectors" if data is None and required=True. + kind = "vectors" + return kind # type: ignore[return-value] def non_ascii_to_octal( From f6d40574c9ae8bae7f25ca77f40c5b729cedcd89 Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Mon, 7 Oct 2024 12:55:24 +0800 Subject: [PATCH 6/6] Apply suggestions from code review Co-authored-by: Wei Ji <23487320+weiji14@users.noreply.github.com> --- pygmt/helpers/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pygmt/helpers/utils.py b/pygmt/helpers/utils.py index 9f099862ec2..055af53e53e 100644 --- a/pygmt/helpers/utils.py +++ b/pygmt/helpers/utils.py @@ -207,7 +207,7 @@ def data_kind( - ``"grid"``: a :class:`xarray.DataArray` object that is not 3-D - ``"image"``: a 3-D :class:`xarray.DataArray` object - ``"stringio"``: a :class:`io.StringIO` object - - ``"matrix"``: anything that is not ``None`` + - ``"matrix"``: anything else that is not ``None`` - ``"vectors"``: ``data`` is ``None`` and ``required=True`` Parameters @@ -302,7 +302,7 @@ def data_kind( case io.StringIO(): kind = "stringio" case (bool() | int() | float()) | None if not required: - # An option argument, mainly for dealing optional virtual files. + # An option argument, mainly for dealing with optional virtual files. kind = "arg" case xr.DataArray(): # An xarray.DataArray object, representing either a grid or an image.