-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Make QuadMesh arguments with defaults keyword_only #20237
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
Nice, I think you are much more lenient than I was going to be. I had this following diff ready to go, which would be your second choice. I'd still vote for skipping the keyword-only deprecation period as I can't imagine many people relying on that "feature". diff --git a/lib/matplotlib/collections.py b/lib/matplotlib/collections.py
index d02607cc5..bcce49440 100644
--- a/lib/matplotlib/collections.py
+++ b/lib/matplotlib/collections.py
@@ -1977,34 +1977,38 @@ class QuadMesh(Collection):
(*meshWidth* * *meshHeight*) quadrilaterals in the mesh. The mesh
need not be regular and the polygons need not be convex.
- A quadrilateral mesh is represented by a (2 x ((*meshWidth* + 1) *
- (*meshHeight* + 1))) numpy array *coordinates*, where each row is
- the *x* and *y* coordinates of one of the vertices. To define the
+ A quadrilateral mesh is represented by a ((*meshWidth* + 1),
+ (*meshHeight* + 1), 2) numpy array *coordinates*, where the final dimension
+ is the *x* and *y* coordinates of one of the vertices. To define the
function that maps from a data point to its corresponding color,
- use the :meth:`set_cmap` method. Each of these arrays is indexed in
- row-major order by the mesh coordinates of the vertex (or the mesh
- coordinates of the lower left vertex, in the case of the colors).
-
- For example, the first entry in *coordinates* is the coordinates of the
- vertex at mesh coordinates (0, 0), then the one at (0, 1), then at (0, 2)
- .. (0, meshWidth), (1, 0), (1, 1), and so on.
+ use the :meth:`set_cmap` method.
*shading* may be 'flat', or 'gouraud'
"""
- def __init__(self, meshWidth, meshHeight, coordinates,
+ def __init__(self, coordinates, *args,
antialiased=True, shading='flat', **kwargs):
super().__init__(**kwargs)
- self._meshWidth = meshWidth
- self._meshHeight = meshHeight
- # By converting to floats now, we can avoid that on every draw.
- self._coordinates = np.asarray(coordinates, float).reshape(
- (meshHeight + 1, meshWidth + 1, 2))
+ if len(args):
+ _api.warn_deprecated("3.5", alternative=(
+ "The QuadMesh class now takes a 3-dimensional *coordinates* "
+ "array as input of shape (nx, ny, 2) that defines the shape "
+ "and size of the mesh."))
+ self._meshWidth = coordinates
+ self._meshHeight = args[0]
+ # By converting to floats now, we can avoid that on every draw.
+ self._coordinates = np.asarray(args[1], float).reshape(
+ (self._meshHeight + 1, self._meshWidth + 1, 2))
+ else:
+ # This will become standard after the deprecation
+ self._coordiantes = np.asarray(coordinates, float)
+ self._meshWidth = self._coordinates.shape[0] - 1
+ self._meshHeight = self._coordinates.shape[1] - 1
+
self._antialiased = antialiased
self._shading = shading
self._bbox = transforms.Bbox.unit()
- self._bbox.update_from_data_xy(coordinates.reshape(
- ((meshWidth + 1) * (meshHeight + 1), 2)))
+ self._bbox.update_from_data_xy(self._coordinates.reshape(-1, 2))
def get_paths(self):
if self._paths is None: |
I'd personally vote for the simpler solution. I expect vanishingly few users use |
I think this can be done by manually writing the deprecation instead? Something like def __init__(self, *args, **kwargs):
old_sig = inspect.signature(lambda self, meshWidth, ...)
new_sig = inspect.signature(lambda self, coordinates, ...)
try:
bound = new_sig.bind(*args, **kwargs)
# extract arguments, do the actual constructor work
...
except TypeError as exc:
try:
bound = old_sig.bind(*args, **kwargs)
# user passed in args using the old call convention
warn_deprecated(...)
# extract arguments, do the actual constructor work
...
except TypeError:
raise exc # probably the new_sig binding error makes more sense
# so that docs and introspection display the new signature
__init__.__signature__ = inspect.signature(
lambda self, coordinates, *, antialiased=True, ...) taking advantage of the fact that we can distinguish an old-style call from a new-style call just from the passed in args? (even ignoring arg types, I don't think(?) a call can ever be correct for both signatures) |
A major part of this PR does not come from the deprecation logic itself. It's rather adapting our internal calls to the new API and tests that the old API still works and produces the same result as the new API. |
c811d1c
to
1f5ad17
Compare
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.
can selfmerge after fixing typos
PR Summary
This is in preparation of changing the signature from
__init__(self, meshWidth, meshHeight, coordinates, antialiased=True, shading='flat', **kwargs)
to
__init__(self, coordinates, *, antialiased=True, shading='flat', **kwargs)
See also: #18472 (comment)
If we want to make this according to deprecation rules this is a multi-step process:
coordinates
keyword-only. (This PR).__init__(self, *args, antialiased=True, shading='flat', **kwargs)
and extractmeshWidth, meshHeight, coordinates
fromargs, kwargs
. At the same time, deprecate passingmeshWidth, meshHeight, 1d_coordinates
in favor of passing 2D coordinates only.__init__(self, coordinates, *, antialiased=True, shading='flat', **kwargs)
The in between
*args
step is essential for a smooth transition phase allowing both signatureswidth, height, 1d_coordinates
and2d_coordinates
.Possible shortcut: Skip the first step and directly go to the
*args
signature. This would be a breaking change, but only for people, who passantialiased
as positional argument.