-
Notifications
You must be signed in to change notification settings - Fork 224
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
Allow passing None explicitly to pygmt functions Part 1 #1857
Conversation
Refactor grdimage to check `if "I" in kwargs` to using `if kwargs.get("I") is not None`.
Specifically when output_type="pandas" too.
Or rather, catch it properly if someone uses spec=None.
I think I'll stop here for now to keep this PR fairly 'small'. There's still a list of other functions that need to be refactored to use
Would someone else be willing to open a Part 2 PR for this? |
I could open part 2. |
Cool, I tried to use the walrus operator in this Part 1 PR but it didn't seem to work for the functions I was refactoring. Maybe you'll have better luck in Part 2 😉 |
Should I open the PR before or after this one is approved/merged? |
You can open the Part 2 PR now if you want, I think there shouldn't be any conflicts. Probably better to work on both in parallel too in case we notice anything wrong with the implementation in one or the other. |
/format |
Just to be safe, let's wait until the Part 2 PR is opened and finalized before merging this into the main branch. I'll keep this PR in draft for now. |
Working on it now! |
I am leaving meca out of part 2, since it is undergoing a complete refactor in #1784. |
@@ -238,8 +238,12 @@ def velo(self, data=None, **kwargs): | |||
""" | |||
kwargs = self._preprocess(**kwargs) # pylint: disable=protected-access |
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.
This isn't really related to the PR, but it's something that I found confusing while working on part 2. Why is kwargs passed to figure._preprocess
? It doesn't look like it is used at all.
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.
Good question, this ensures that velo
is plotted to the right instance of the figure (e.g. if someone does fig1
, fig2
, etc). See also #1072 (comment). The _preprocess
code is here:
Lines 109 to 115 in 0aa04d7
def _preprocess(self, **kwargs): | |
""" | |
Call the ``figure`` module before each plotting command to ensure we're | |
plotting to this particular figure. | |
""" | |
self._activate_figure() | |
return kwargs |
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.
It makes sense to me why we call the figure method to ensure the correct figure is activated in the session. I still don't really understand why we pass and return kwargs to/from _preprocess
, or even why we call _preprocess
at all rather than calling _activate_figure
directly. I pushed a new branch to demonstrate the point of confusion, in which I replaced all the kwargs = self._preprocess(**kwargs)
with self._activate_figure
which seems more readable, a tiny bit faster, and still seems to work fine.
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.
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.
This was setup for any other preprocessing of kwargs that may be needed or other figure plotting methods. At the time, I put this in place to allow things like passing pygmt.Figure(projection=pygmt.Mercator(), width="25c")
and then inserting the projection code into the first plot command.
It could also be useful for any bookkeeping operation that is needed, like activating the figure, activating a subplot, etc.
pygmt/src/grdgradient.py
Outdated
if kwargs.get("G") is None: # if outgrid is unset, output to tempfile | ||
kwargs.update({"G": tmpfile.name}) | ||
outgrid = kwargs["G"] |
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.
if kwargs.get("G") is None: # if outgrid is unset, output to tempfile | |
kwargs.update({"G": tmpfile.name}) | |
outgrid = kwargs["G"] | |
if (outgrid := kwargs.get("G")) is None: | |
kwargs["G"] = outgrid = tmpfile.name # output to tmpfile |
I think this is slightly more readable (inspired by item number 16 in Effective Python (2021)).
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.
Ok, my brain is telling me that there's a reason not to do variable assignment like a = b = "c"
, something about how changing b
would also change a
but after some testing, it seems to be ok. Maybe I'm just thinking of some other programming language I've used before like Matlab, Javascript or Python 2 🤷
Co-authored-by: Meghan Jones <[email protected]>
Search for
|
Oops, not sure how I missed all of that. Looks like we need a Part 3 😅 Do you want to open up that PR @seisman? |
OK, I'll open a PR later. |
…ngTools#1857) Implements a more robust check for None values in pygmt functions. * Let grdimage shading=None or False work Refactor grdimage to check `if "I" in kwargs` to using `if kwargs.get("I") is not None`. * Let grd2cpt's categorical, cyclic and output work with None input * Let grd2xyz's outcols work with None input Specifically when output_type="pandas" too. * Let grdgradient's tiles, normalize and outgrid work with None input * Let grdview's drapegrid work with None inputs * Let makecpt's categorical, cyclic and output work with None inputs * Let plot's style, color, intensity and transparency work with None input * Let plot3d's style, color, intensity & transparency work with None input * Let solar's T work with None input * Let transparency work with 0, None and False input * Let project's center, convention and generate work with None inputs * Let velo's spec work with None inputs Or rather, catch it properly if someone uses spec=None. * Update pygmt/src/grdgradient.py using walrus operator Co-authored-by: Meghan Jones <[email protected]> Co-authored-by: Dongdong Tian <[email protected]>
Description of proposed changes
Several PyGMT functions have
None
as the default value (as seen in the docstring), but if a user were to explicitly set aNone
argument, this can fail. This Pull Request implements a more robust check forNone
values, as discussed in #1665 (comment)For example, in the case of
grdimage
, instead of checkingif "I" in kwargs
, it is usually better to doif kwargs.get("I") is not None
.TODO:
Fixes #1852, closes #1807
Reminders
make format
andmake check
to make sure the code follows the style guide.doc/api/index.rst
.Slash Commands
You can write slash commands (
/command
) in the first line of a comment to performspecific operations. Supported slash commands are:
/format
: automatically format and lint the code/test-gmt-dev
: run full tests on the latest GMT development version