Skip to content

MNT: Deprecate FontProperties(pattern) #28837

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

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions doc/api/next_api_changes/deprecations/28837-TH.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FontProperties(pattern)
~~~~~~~~~~~~~~~~~~~~~~~

Passing a single string parameter as fontconfig pattern to `.FontProperties` is
deprecated. Use `.FontProperties.from_pattern` instead.
54 changes: 42 additions & 12 deletions lib/matplotlib/font_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -585,18 +585,22 @@ class FontProperties:
approach allows all text sizes to be made larger or smaller based
on the font manager's default font size.

This class will also accept a fontconfig_ pattern_, if it is the only
argument provided. This support does not depend on fontconfig; we are
merely borrowing its pattern syntax for use here.

.. _fontconfig: https://www.freedesktop.org/wiki/Software/fontconfig/
.. _pattern:
https://www.freedesktop.org/software/fontconfig/fontconfig-user.html

Note that Matplotlib's internal font manager and fontconfig use a
different algorithm to lookup fonts, so the results of the same pattern
may be different in Matplotlib than in other applications that use
fontconfig.
.. deprecated:: 3.10

**Use `.FontProperties.from_pattern` instead.**

This class will also accept a fontconfig_ pattern_, if it is the only
argument provided. This support does not depend on fontconfig; we are
merely borrowing its pattern syntax for use here.

.. _fontconfig: https://www.freedesktop.org/wiki/Software/fontconfig/
.. _pattern:
https://www.freedesktop.org/software/fontconfig/fontconfig-user.html

Note that Matplotlib's internal font manager and fontconfig use a
different algorithm to lookup fonts, so the results of the same pattern
may be different in Matplotlib than in other applications that use
fontconfig.
"""

def __init__(self, family=None, style=None, variant=None, weight=None,
Expand All @@ -617,8 +621,34 @@ def __init__(self, family=None, style=None, variant=None, weight=None,
if (isinstance(family, str)
and style is None and variant is None and weight is None
and stretch is None and size is None and fname is None):
_api.warn_deprecated(
"3.10",
message="Passing a single string as fontconfig pattern to "
"FontProperties is deprecated. Use "
"FontProperties.from_pattern() instead.")
self.set_fontconfig_pattern(family)

@classmethod
def from_pattern(cls, pattern):
"""
Create FontProperties from a fontconfig_ pattern_.

.. _fontconfig: https://www.freedesktop.org/wiki/Software/fontconfig/
.. _pattern:
https://www.freedesktop.org/software/fontconfig/fontconfig-user.html

This support does not depend on fontconfig; we are merely borrowing its
pattern syntax for use here.

Note that Matplotlib's internal font manager and fontconfig use a
different algorithm to lookup fonts, so the results of the same pattern
may be different in Matplotlib than in other applications that use
fontconfig.
"""
prop = FontProperties()
prop.set_fontconfig_pattern(pattern)
return prop

@classmethod
def _from_any(cls, arg):
"""
Expand Down
2 changes: 2 additions & 0 deletions lib/matplotlib/font_manager.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ class FontProperties:
fname: str | os.PathLike | Path | None = ...,
math_fontfamily: str | None = ...,
) -> None: ...
@classmethod
def from_pattern(cls, pattern: str) -> FontProperties: ...
def __hash__(self) -> int: ...
def __eq__(self, other: object) -> bool: ...
def get_family(self) -> list[str]: ...
Expand Down
34 changes: 28 additions & 6 deletions lib/matplotlib/tests/test_fontconfig_pattern.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import pytest

from matplotlib import _api
from matplotlib.font_manager import FontProperties


Expand All @@ -21,7 +22,7 @@
f1 = FontProperties()
s = str(f1)

f2 = FontProperties(s)
f2 = FontProperties.from_pattern(s)
for k in keys:
assert getattr(f1, k)() == getattr(f2, k)(), test + k

Expand All @@ -30,7 +31,7 @@
f1 = FontProperties(family="serif", size=20, style="italic")
s = str(f1)

f2 = FontProperties(s)
f2 = FontProperties.from_pattern(s)
for k in keys:
assert getattr(f1, k)() == getattr(f2, k)(), test + k

Expand All @@ -41,11 +42,26 @@
stretch="expanded")
s = str(f1)

f2 = FontProperties(s)
f2 = FontProperties.from_pattern(s)
for k in keys:
assert getattr(f1, k)() == getattr(f2, k)(), test + k


def test_fontconfig_pattern_deprecated():
"""
Make sure (at one example) that the deprecated API still works.

Same test as test_fontconfig_pattern test="basic", but with the deprecate API.
"""
f1 = FontProperties(family="serif", size=20, style="italic")
s = str(f1)

with _api.suppress_matplotlib_deprecation_warning:
f2 = FontProperties(s)

Check warning on line 60 in lib/matplotlib/tests/test_fontconfig_pattern.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/tests/test_fontconfig_pattern.py#L60

Added line #L60 was not covered by tests
for k in keys:
assert getattr(f1, k)() == getattr(f2, k)()

Check warning on line 62 in lib/matplotlib/tests/test_fontconfig_pattern.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/tests/test_fontconfig_pattern.py#L62

Added line #L62 was not covered by tests


def test_fontconfig_str():
"""Test FontProperties string conversions for correctness."""

Expand All @@ -56,15 +72,15 @@
test = "defaults "
s = ("sans\\-serif:style=normal:variant=normal:weight=normal"
":stretch=normal:size=12.0")
font = FontProperties(s)
font = FontProperties.from_pattern(s)
right = FontProperties()
for k in keys:
assert getattr(font, k)() == getattr(right, k)(), test + k

test = "full "
s = ("serif-24:style=oblique:variant=small-caps:weight=bold"
":stretch=expanded")
font = FontProperties(s)
font = FontProperties.from_pattern(s)
right = FontProperties(family="serif", size=24, weight="bold",
style="oblique", variant="small-caps",
stretch="expanded")
Expand All @@ -74,4 +90,10 @@

def test_fontconfig_unknown_constant():
with pytest.raises(ValueError, match="ParseException"):
FontProperties(":unknown")
FontProperties.from_pattern(":unknown")


def test_fontconfig_unknown_constant_depreacted():
with _api.suppress_matplotlib_warnings():
with pytest.raises(ValueError, match="ParseException"):
FontProperties(":unknown")

Check warning on line 99 in lib/matplotlib/tests/test_fontconfig_pattern.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/tests/test_fontconfig_pattern.py#L99

Added line #L99 was not covered by tests
Loading