Skip to content

Fix cl subgridspec #22144

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

Merged
merged 3 commits into from
Jan 9, 2022
Merged

Fix cl subgridspec #22144

merged 3 commits into from
Jan 9, 2022

Conversation

jklymak
Copy link
Member

@jklymak jklymak commented Jan 7, 2022

PR Summary

Closes #22143

If subgridspecs were identical, then their strings were identical, and the dictionary we had for the layoutgrids was being addressed with the same key twice. Changed the key to a unique repr for the subgridspec.

PR Checklist

Tests and Styling

  • Has pytest style unit tests (and pytest passes).
  • Is Flake 8 compliant (install flake8-docstrings and run flake8 --docstring-convention=all).

Documentation

  • New features are documented, with examples if plot related.
  • New features have an entry in doc/users/next_whats_new/ (follow instructions in README.rst there).
  • API changes documented in doc/api/next_api_changes/ (follow instructions in README.rst there).
  • Documentation is sphinx and numpydoc compliant (the docs should build without error).

@jklymak jklymak added this to the v3.5.2 milestone Jan 7, 2022
@jklymak jklymak added topic: geometry manager LayoutEngine, Constrained layout, Tight layout Release critical For bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions. labels Jan 7, 2022
Comment on lines 206 to 207
# get a unique representation:
rep = object.__repr__(gs) + 'top'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you not simply use the memory address of the object: id(gs)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure. gs is used as a key as well, so I wanted to differentiate.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the use of the key is to 1) be unique to each gridspec and 2) does not need to be human readable, I would go with using id(gs). Either way, I think the keys should be of a similar type, so it would be good to modify the if block above this to use either id(gs) or object.__repr__(gs).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The whole set of code usually just uses layoutgrid[obj] where obj is the actual object, be it a gridspec, figure etc. We could make them all be layoutgrid[id(obj)] but that would introduce a lot of extra typing.

Here, this is just a dummy shell so that the hierarchy of subgridspecs is the same as other objects, in that they all have a parent that can hold suptitles, etc. There is no associated object on the figure corresponding to this, so I just am using a dummy here. The problem with the original code is that the dummy wasn't unique!

We can certainly use id, but that loses any hint of what the object was in the key. object.__repr__ keeps the type info and the id. i.e. for this case we get a string "<matplotlib.gridspec.GridSpecFromSubplotSpec object at 0x17b686790>top"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another thought - since __repr__ is typically a string that can be passed to eval() to create an identical copy of the object, it isn't always unique, e.g.:

>>> 'abc'.__repr__()
"'abc'"

So I would still say if you want to guarentee uniqueness, use id() in case we change GridSpecFromSubplotSpec.__repr__ to a non-instance-unique string in the future.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When we use the base class object.__repr__, this should always result in f"<{gs.__class__.__name__} object at {id(gs)}>". Uniqueness should be guaranteed. But maybe just just the explicit formatting instead of the slightly unusual object.__repr__.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could perhaps use layoutgrids[(gs, "top")] (which can even be spelled layoutgrid[gs, "top"]).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah OK, thats reasonable. It really never gets referenced except by the child via child.parent, so it just needs to be identifiable for debug purposes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Newest commit just uses the tuple...

@timhoffm timhoffm merged commit b3f61d1 into matplotlib:main Jan 9, 2022
meeseeksmachine pushed a commit to meeseeksmachine/matplotlib that referenced this pull request Jan 9, 2022
timhoffm added a commit that referenced this pull request Jan 9, 2022
…144-on-v3.5.x

Backport PR #22144 on branch v3.5.x (Fix cl subgridspec)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Release critical For bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions. topic: geometry manager LayoutEngine, Constrained layout, Tight layout
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Bug]: constrained_layout merging similar subgrids
4 participants