-
Notifications
You must be signed in to change notification settings - Fork 229
data_kind: Refactor the if-else statements into match-case statements #3481
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
0c82b3c
0eb4f8f
3d8be4d
1936e2b
048762a
2b34b67
33051ac
f6d4057
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -187,23 +187,27 @@ | |||||
return "ISOLatin1+" | ||||||
|
||||||
|
||||||
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. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Making |
||||||
) -> Literal[ | ||||||
"arg", "file", "geojson", "grid", "image", "matrix", "stringio", "vectors" | ||||||
]: | ||||||
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 types. Following data kinds are recognized: | ||||||
seisman marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
||||||
- 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, | ||||||
seisman marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
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) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe this highlighting exists also for
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function is not documented in the API documentation page, so linking |
||||||
- ``"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 | ||||||
seisman marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
- ``"vectors"``: data is ``None`` and ``required=True`` | ||||||
seisman marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
||||||
Parameters | ||||||
---------- | ||||||
|
@@ -287,30 +291,36 @@ | |||||
>>> data_kind(data=None) | ||||||
'vectors' | ||||||
""" | ||||||
kind: Literal[ | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This type hint is no longer needed. |
||||||
"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( | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PLR0911 means "too-many-return-statements".
https://docs.astral.sh/ruff/rules/too-many-return-statements/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see much of an improvement in readability/maintainability between the previous
if-elif-else
statements and theif-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 theif-elif-else
syntax, or usematch-case
instead.If using
match-case
, would it be more readable to do theisinstance()
checks first, and then have a nestedif-elif
forcase _
for the more complex cases?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel
match-case
would make it more complicated:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using
match-case
also has thetoo-many-return-statements
warning, and usingif-elif-else
means we need to type hints thekind
variable like:Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
match-case
statements look more compact. Done in 33051ac.The mypy warning is also suppressed.