Skip to content
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

add documentation for reloading font cache #26453

Closed
wants to merge 1 commit into from

Conversation

saranti
Copy link
Contributor

@saranti saranti commented Aug 4, 2023

PR summary

Closes #24872. Adds documentation that describes the process of making newly added fonts available to the fontmanager.

  • Made public the load_fontmanager method which can be used in place of the deprecated matplotlib.font_manager._rebuild() method.
  • Added a new Loading new fonts section to the fonts-in-matplotlib doc with an explanation of the methods of reloading the font cache, with example code.

PR checklist

@saranti saranti marked this pull request as draft August 4, 2023 13:29
@story645 story645 added New feature Documentation: user guide files in galleries/users_explain or doc/users labels Aug 4, 2023
yourself if your new fonts cannot be found by Matplotlib.
The cache can be rebuilt by using :func:`matplotlib.font_manager.load_fontmanager`::
import matplotlib as mpl
mpl.font_manager.load_fontmanager(try_read_cache=False)
Copy link
Member

Choose a reason for hiding this comment

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

I don't think that this will actually work?

This will make a new font manager and return it to you, but it will not change the singleton that is used by the rest of the library or update the findfont and get_font_names held at the module level.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My testing procedure for this was:

  • add a new font to mpl-data\fonts\ttf
  • run a short plot with a text instance with family=new font
  • see that the text doesn't update to the new font after multiple runs
  • run the font_manager.load_fontmanager code
  • run the plot again

Now the text is now set to the new font and a new entry in the font cache is present. The findfont and get_font_names methods both return the new font.
I did notice however, that the before and after fontmanager instances were the same object with the same ID.

Copy link
Member

Choose a reason for hiding this comment

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

... ok, I do not understand why that works 🤯

Copy link
Member

Choose a reason for hiding this comment

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

ok, question: are you running this all in the same process or each in its own Python process?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Each in their own separate process.

@tacaswell
Copy link
Member

Unfortunately I do not think it is this simple because we keep a singleton of this cache and then re-expose its methods at the module level.

I think the steps here are:

  • keep the load function private
  • write top-level functions that replace find_font and get_font_names (minor API break but we need it to make sure if someone does from matplotlib.font_manager import find_font and then we update the cache the function they are holding onto is not the old one...I guess we could fake the method properties on a function but it is not worth it)
  • write a new top level function like reload_fontcache or something similar name that updates the fontManager singleton. If someone has done from matplotlib.font_manager import fontManager I think we are stuck in a world where they will still have a reference to the old one! I guess we could deprecate it as a publicly accessible

An alternate path would be to update FontManager to be able to have its internal state updated.

@tacaswell tacaswell added this to the v3.9.0 milestone Aug 4, 2023
@tacaswell
Copy link
Member

An alternate to my last comment is to explain why this does work as it looks like it creates a new FontManger that we then throw away, but some how the existing FontManager is changed?

@anntzer
Copy link
Contributor

anntzer commented Aug 8, 2023

Haven't read through the whole issue, but note that in the rebuild_if_missing branch at the end of findfont_cached, fontManager calls _load_fontmanager then replaces its __dict__ with the contents of the newly loaded instance (so the old one really becomes a copy of the new one).

See also #13810/#13852, which may be worth revisiting?

@tacaswell
Copy link
Member

That is a bit heavy handed, but makes sense (a recache method might be better).

However the way this is hidden behind a cache, we will only automatically discover the new font if it is there when we search for it. It might be worth also adding a public way to clear that cache.

@saranti saranti closed this Mar 23, 2024
@saranti saranti deleted the load_custom_font branch March 23, 2024 05:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Documentation: user guide files in galleries/users_explain or doc/users New feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Doc]: Documentation should clearly describe how a user can make matplotlib load custom fonts per default
4 participants