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

(De-Duplication) linking validate hatch from hatch module #28076

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
2 changes: 2 additions & 0 deletions lib/matplotlib/hatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ def __init__(self, hatch, density):
def _validate_hatch_pattern(hatch):
valid_hatch_patterns = set(r'-+|/\xXoO.*')
if hatch is not None:
if not isinstance(hatch, str):
Copy link
Member

Choose a reason for hiding this comment

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

This is an subtle API change that needs to be document as currently

b.set_hatch(('x','x'))

works. The docstring on Patch.set_hatch is not clear about the type on the input should be.

We do run the hatches through an lrucache so only hashable things work (and it looks like we used as a key in a dictionary before that).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Working on it,
I'm a bit lost on -

We do run the hatches through an lrucache so only hashable things work (and it looks like we used as a key in a dictionary before that).

Could you break it down for me

Copy link
Member

Choose a reason for hiding this comment

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

@staticmethod
@lru_cache(8)
def hatch(hatchpattern, density=6):
"""
Given a hatch specifier, *hatchpattern*, generates a `Path` that
can be used in a repeated hatching pattern. *density* is the
number of lines per unit square.
"""
from matplotlib.hatch import get_path
return (get_path(hatchpattern, density)
if hatchpattern is not None else None)

Is part of the code path between Patch.set_hatch and rendering a hatched patch. The lru_cache means we will avoid re-computing the hatch path. The lru_cache is backed by a dictionary (eventually) with the function parameters as the key so only inputs that are hashable can be used.

raise ValueError("Hatch pattern must be a string")
invalids = set(hatch).difference(valid_hatch_patterns)
if invalids:
valid = ''.join(sorted(valid_hatch_patterns))
Expand Down
15 changes: 2 additions & 13 deletions lib/matplotlib/rcsetup.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from matplotlib.colors import Colormap, is_color_like
from matplotlib._fontconfig_pattern import parse_fontconfig_pattern
from matplotlib._enums import JoinStyle, CapStyle
from matplotlib.hatch import _validate_hatch_pattern

# Don't let the original cycler collide with our validating cycler
from cycler import Cycler, cycler as ccycler
Expand Down Expand Up @@ -617,19 +618,7 @@ def _validate_int_greaterequal0(s):
raise RuntimeError(f'Value must be >=0; got {s}')


def validate_hatch(s):
r"""
Validate a hatch pattern.
A hatch pattern string can have any sequence of the following
characters: ``\ / | - + * . x o O``.
"""
if not isinstance(s, str):
raise ValueError("Hatch pattern must be a string")
_api.check_isinstance(str, hatch_pattern=s)
unknown = set(s) - {'\\', '/', '|', '-', '+', '*', '.', 'x', 'o', 'O'}
if unknown:
raise ValueError("Unknown hatch symbol(s): %s" % list(unknown))
return s
validate_hatch = _validate_hatch_pattern


validate_hatchlist = _listify_validator(validate_hatch)
Expand Down
2 changes: 1 addition & 1 deletion lib/matplotlib/rcsetup.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ def _validate_linestyle(s: Any) -> LineStyleType: ...
def validate_markeverylist(s: Any) -> list[MarkEveryType]: ...
def validate_bbox(s: Any) -> Literal["tight", "standard"] | None: ...
def validate_sketch(s: Any) -> None | tuple[float, float, float]: ...
def validate_hatch(s: Any) -> str: ...
def validate_hatch(hatch: Any) -> str: ...
def validate_hatchlist(s: Any) -> list[str]: ...
def validate_dashlist(s: Any) -> list[list[float]]: ...

Expand Down
3 changes: 1 addition & 2 deletions lib/matplotlib/tests/test_rcparams.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,8 +311,7 @@ def generate_validator_testcases(valid):
'success': (('--|', '--|'), ('\\oO', '\\oO'),
('/+*/.x', '/+*/.x'), ('', '')),
'fail': (('--_', ValueError),
(8, ValueError),
('X', ValueError)),
(8, ValueError)),
},
{'validator': validate_colorlist,
'success': (('r,g,b', ['r', 'g', 'b']),
Expand Down