data_kind: Refactor the if-else statements into match-case statements#3481
data_kind: Refactor the if-else statements into match-case statements#3481
Conversation
pygmt/helpers/utils.py
Outdated
|
|
||
|
|
||
| def data_kind( | ||
| def data_kind( # noqa: PLR0911 |
There was a problem hiding this comment.
PLR0911 means "too-many-return-statements".
https://docs.astral.sh/ruff/rules/too-many-return-statements/
There was a problem hiding this comment.
This PR refactors the data_kind function, to use if-return statements instead of if-else statements. The new if-return statements are easier to read and maintain.
I don't see much of an improvement in readability/maintainability between the previous if-elif-else statements and the if-return style in this PR. Looking at https://stackoverflow.com/questions/72024229/how-to-solve-pylint-too-many-return-statements-elegantly, I'm thinking if we could either keep the if-elif-else syntax, or use match-case instead.
If using match-case, would it be more readable to do the isinstance() checks first, and then have a nested if-elif for case _ for the more complex cases?
There was a problem hiding this comment.
I feel match-case would make it more complicated:
match data:
case x if isinstance(x, io.StringIO):
return "stringio"
case x if isinstance(x, xr.DataArray):
return "image" if len(x.dims) == 3 else "grid"
case x if isinstance(x, bool | int | float) or (x is None and not required):
return "arg"
There was a problem hiding this comment.
Using match-case also has the too-many-return-statements warning, and using if-elif-else means we need to type hints the kind variable like:
kind: Literal["arg", "file", "geojson", "grid", "image", "matrix", "stringio", "vectors"]
There was a problem hiding this comment.
Haven't run tests on this, but we can remove some of the isinstance() calls like so using class patterns (xref https://stackoverflow.com/questions/67524641/convert-multiple-isinstance-checks-to-structural-pattern-matching/67524642#67524642)
match data:
case str() | pathlib.PurePath():
kind = "file"
case list() | tuple() if all(
isinstance(_file, str | pathlib.PurePath) for _file in data
):
kind = "file"
case io.StringIO():
kind = "stringio"
case (bool() | int() | float()) | None if not required:
kind = "arg"
case xr.DataArray():
kind = "image" if len(data.dims) == 3 else "grid"
case x if hasattr(x, "__geo_interface__"):
kind = "geojson"
case x if x is not None:
kind = "matrix"
case _:
kind = "vectors"
return kindThere was a problem hiding this comment.
The match-case statements look more compact. Done in 33051ac.
The mypy warning is also suppressed.
| >>> data_kind(data=None) | ||
| 'vectors' | ||
| """ | ||
| kind: Literal[ |
There was a problem hiding this comment.
This type hint is no longer needed.
| def data_kind( | ||
| data: Any = None, required: bool = True | ||
| def data_kind( # noqa: PLR0911 | ||
| data: Any, required: bool = True |
There was a problem hiding this comment.
Making data a required parameter here.
|
Will merge in 24 hours. |
| - ``"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) |
There was a problem hiding this comment.
Maybe this highlighting exists also for shapely.geometry?
| (e.g., geopandas.GeoDataFrame or shapely.geometry) | |
| (e.g., :class:`geopandas.GeoDataFrame` or shapely.geometry) |
There was a problem hiding this comment.
This function is not documented in the API documentation page, so linking shapely.geometry or not makes little difference.
Co-authored-by: Yvonne Fröhlich <94163266+yvonnefroehlich@users.noreply.github.com>
Co-authored-by: Wei Ji <23487320+weiji14@users.noreply.github.com>
Description of proposed changes
Follow-up PR after PR #3480.
This PR refactors the
data_kindfunction, to usematch-casestatements instead ofif-elsestatements.This PR also updates the docstrings.