-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Factor out common code between Patch.draw and FancyArrowPatch.draw. #11741
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
Conversation
I don't follow context managers well enough to follow this code. Do you need to use a context manager to do this or can it just be factored out as a method or helper function? I don't understand why this would conceptually be a "context". |
Essentially, the context manager allows to refactor
into
(This can essentially be read as "run the context manager code, inserting the indented contents of the with-block at the place of the yield".) I could instead provide a |
No thats fine. I think I understand now. If you want to make it more clear for those of us w/ a more rudimentary understanding of the language feature set, you could comment the init and cleanup sections. You could also comment the |
Added a comment at the level of the yield, I hope it helps. Feel free to propose a rewording. |
if self._edgecolor[3] == 0: | ||
lw = 0 | ||
gc.set_linewidth(lw) | ||
gc.set_dashes(self._dashoffset, self._dashes) |
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 context uses gc.set_dashes(0, self._dashes)
instead.
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.
Indeed, I had missed that. I restored the old behavior using setattr_cm (in Patch.draw), leaving a comment similar to the one for the capstyle in FancyArrowPatch.
|
||
gc.set_antialiased(self._antialiased) | ||
self._set_gc_clip(gc) | ||
gc.set_capstyle('round') |
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 context uses gc.set_capstyle(self._capstyle)
instead. This is 'butt' by default (inherited from Patch
). It's reasonable to draw the value from self._capstyle
. Should the default for this value be 'round' to have backward compatibility or do you want to change it intentionally to be the same default as for Patch
?
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 forced it to "round" above (in the setattr_cm). Yes, ignoring the capstyle was probably a long-standing bug (the kind of things that such refactors uncover...) but changing that would result in changes in the baseline images (... that's how I realized the discrepancy). I'll leave this as it is until someone actually complains or we have some othe reason to change the baseline images.
lib/matplotlib/patches.py
Outdated
renderer.close_group('patch') | ||
self.stale = False | ||
for p, f in zip(path, fillable): | ||
draw_path(p, affine, self._facecolor if f else None) |
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.
doesn't need self._facecolor
the same workaround for fully transparent values as above (self._facecolor if self._facecolor[3] else None
).
Also in the original function rgbFace
was used, which changed alpha=0 to alpha=None
rgbFace = self._facecolor
if rgbFace[3] == 0:
rgbFace = None # (some?) renderers expect this as no-fill signal
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.
Fixed to
for p, f in zip(path, fillable):
draw_path(
p, affine,
self._facecolor if f and self._facecolor[3] else None)
which should handle both issues.
lib/matplotlib/patches.py
Outdated
""" | ||
``draw()`` helper factored out for sharing with `FancyArrowPatch`. | ||
|
||
Yields a callable that can be called as a bound ``draw_path`` method |
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.
Would this be more clear?
Yields a
draw_path
-like function that is bound to theGraphicsContext
of the renderer. Technically, this is apartial
function ofdraw_path
with the first argument (theGraphicsContext
) already filled in. The arguments of the returned function are the remaining arguements ofdraw_path
.
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.
reworded the docstring to something else...
lib/matplotlib/patches.py
Outdated
if not self.get_visible(): | ||
return | ||
@contextlib.contextmanager | ||
def _prepare_path_drawer(self, renderer): |
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.
An alternative name could be _bind_draw_path_function
. This would result in
with self._bind_draw_path_function(renderer) as draw_path:
...
A bit longish but maybe also a bit more telling. I don't have strong feelings on this. Leave it or use it.
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.
done
Comments addressed as a separate commit for ease of review, but would suggest squashing when merging. |
Good to go. I'm not sure about the milestone. Is this still for 3.0 or should this go in 3.1? Anyone can merge (and squash), once this is decided. |
Squashed and rebased, will self-merge into master (not 3.0) once CI passes per comment above. |
The code setting up the renderer and gc are nearly identical, so we can factor it out as a helper contextmanager. The only difference is that FancyArrowPatch then calls draw_path multiple times with various arguments. Note that the refactoring exposed the fact that FancyArrowPatches are (incorrectly, IMO) ignoring joinstyles and capstyles (this is necessary to make image test pass, but we probably will want to generate new images with the "correct" (non-ignoring) behavior at some point).
CI failure is spurious (apt-get complaining), self-merging per above. |
The code setting up the renderer and gc are nearly identical, so we can
factor it out as a helper contextmanager. The only difference is that
FancyArrowPatch then calls draw_path multiple times with various
arguments.
Note that the refactoring exposed the fact that FancyArrowPatches are
(incorrectly, IMO) ignoring joinstyles and capstyles (this is necessary
to make image test pass, but we probably will want to generate new
images with the "correct" (non-ignoring) behavior at some point).
PR Summary
PR Checklist