Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb9c5152

Browse files
authored
Merge pull request#24257 from anntzer/style
Load style files from third-party packages.
2 parentsaca6e9d +24be778 commitb9c5152

File tree

10 files changed

+127
-61
lines changed

10 files changed

+127
-61
lines changed

‎.github/workflows/tests.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,8 @@ jobs:
162162
163163
# Install dependencies from PyPI.
164164
python -m pip install --upgrade $PRE \
165-
'contourpy>=1.0.1' cycler fonttools kiwisolvernumpy packaging \
166-
pillow pyparsing python-dateutil setuptools-scm \
165+
'contourpy>=1.0.1' cycler fonttools kiwisolverimportlib_resources \
166+
numpy packagingpillow pyparsing python-dateutil setuptools-scm \
167167
-r requirements/testing/all.txt \
168168
${{ matrix.extra-requirements }}
169169
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
importlib_resources>=2.3.0 is now required on Python<3.10
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

‎doc/devel/dependencies.rst‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ reference.
2626
* `Pillow<https://pillow.readthedocs.io/en/latest/>`_ (>= 6.2)
2727
* `pyparsing<https://pypi.org/project/pyparsing/>`_ (>= 2.3.1)
2828
* `setuptools<https://setuptools.readthedocs.io/en/latest/>`_
29+
* `pyparsing<https://pypi.org/project/pyparsing/>`_ (>= 2.3.1)
30+
* `importlib-resources<https://pypi.org/project/importlib-resources/>`_
31+
(>= 3.2.0; only required on Python < 3.10)
2932

3033

3134
.. _optional_dependencies:
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
Style files can be imported from third-party packages
2+
-----------------------------------------------------
3+
4+
Third-party packages can now distribute style files that are globally available
5+
as follows. Assume that a package is importable as ``import mypackage``, with
6+
a ``mypackage/__init__.py`` module. Then a ``mypackage/presentation.mplstyle``
7+
style sheet can be used as ``plt.style.use("mypackage.presentation")``.
8+
9+
The implementation does not actually import ``mypackage``, making this process
10+
safe against possible import-time side effects. Subpackages (e.g.
11+
``dotted.package.name``) are also supported.

‎environment.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ dependencies:
1212
-contourpy>=1.0.1
1313
-cycler>=0.10.0
1414
-fonttools>=4.22.0
15+
-importlib-resources>=3.2.0
1516
-kiwisolver>=1.0.1
1617
-numpy>=1.19
1718
-pillow>=6.2

‎lib/matplotlib/style/core.py‎

Lines changed: 73 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,18 @@
1515
importlogging
1616
importos
1717
frompathlibimportPath
18+
importsys
1819
importwarnings
1920

21+
ifsys.version_info>= (3,10):
22+
importimportlib.resourcesasimportlib_resources
23+
else:
24+
# Even though Py3.9 has importlib.resources, it doesn't properly handle
25+
# modules added in sys.path.
26+
importimportlib_resources
27+
2028
importmatplotlibasmpl
21-
frommatplotlibimport_api,_docstring,rc_params_from_file,rcParamsDefault
29+
frommatplotlibimport_api,_docstring,_rc_params_in_file,rcParamsDefault
2230

2331
_log=logging.getLogger(__name__)
2432

@@ -64,23 +72,6 @@
6472
"directly use the seaborn API instead.")
6573

6674

67-
def_remove_blacklisted_style_params(d,warn=True):
68-
o= {}
69-
forkeyind:# prevent triggering RcParams.__getitem__('backend')
70-
ifkeyinSTYLE_BLACKLIST:
71-
ifwarn:
72-
_api.warn_external(
73-
f"Style includes a parameter,{key!r}, that is not "
74-
"related to style. Ignoring this parameter.")
75-
else:
76-
o[key]=d[key]
77-
returno
78-
79-
80-
def_apply_style(d,warn=True):
81-
mpl.rcParams.update(_remove_blacklisted_style_params(d,warn=warn))
82-
83-
8475
@_docstring.Substitution(
8576
"\n".join(map("- {}".format,sorted(STYLE_BLACKLIST,key=str.lower)))
8677
)
@@ -99,20 +90,28 @@ def use(style):
9990
Parameters
10091
----------
10192
style : str, dict, Path or list
102-
A style specification. Valid options are:
10393
104-
+------+-------------------------------------------------------------+
105-
| str | The name of a style or a path/URL to a style file. For a |
106-
| | list of available style names, see `.style.available`. |
107-
+------+-------------------------------------------------------------+
108-
| dict | Dictionary with valid key/value pairs for |
109-
| | `matplotlib.rcParams`. |
110-
+------+-------------------------------------------------------------+
111-
| Path | A path-like object which is a path to a style file. |
112-
+------+-------------------------------------------------------------+
113-
| list | A list of style specifiers (str, Path or dict) applied from |
114-
| | first to last in the list. |
115-
+------+-------------------------------------------------------------+
94+
A style specification.
95+
96+
- If a str, this can be one of the style names in `.style.available`
97+
(a builtin style or a style installed in the user library path).
98+
99+
This can also be a dotted name of the form "package.style_name"; in
100+
that case, "package" should be an importable Python package name,
101+
e.g. at ``/path/to/package/__init__.py``; the loaded style file is
102+
``/path/to/package/style_name.mplstyle``. (Style files in
103+
subpackages are likewise supported.)
104+
105+
This can also be the path or URL to a style file, which gets loaded
106+
by `.rc_params_from_file`.
107+
108+
- If a dict, this is a mapping of key/value pairs for `.rcParams`.
109+
110+
- If a Path, this is the path to a style file, which gets loaded by
111+
`.rc_params_from_file`.
112+
113+
- If a list, this is a list of style specifiers (str, Path or dict),
114+
which get applied from first to last in the list.
116115
117116
Notes
118117
-----
@@ -129,33 +128,52 @@ def use(style):
129128

130129
style_alias= {'mpl20':'default','mpl15':'classic'}
131130

132-
deffix_style(s):
133-
ifisinstance(s,str):
134-
s=style_alias.get(s,s)
135-
ifsin_DEPRECATED_SEABORN_STYLES:
131+
forstyleinstyles:
132+
ifisinstance(style,str):
133+
style=style_alias.get(style,style)
134+
ifstylein_DEPRECATED_SEABORN_STYLES:
136135
_api.warn_deprecated("3.6",message=_DEPRECATED_SEABORN_MSG)
137-
s=_DEPRECATED_SEABORN_STYLES[s]
138-
returns
139-
140-
forstyleinmap(fix_style,styles):
141-
ifnotisinstance(style, (str,Path)):
142-
_apply_style(style)
143-
elifstyle=='default':
144-
# Deprecation warnings were already handled when creating
145-
# rcParamsDefault, no need to reemit them here.
146-
with_api.suppress_matplotlib_deprecation_warning():
147-
_apply_style(rcParamsDefault,warn=False)
148-
elifstyleinlibrary:
149-
_apply_style(library[style])
150-
else:
136+
style=_DEPRECATED_SEABORN_STYLES[style]
137+
ifstyle=="default":
138+
# Deprecation warnings were already handled when creating
139+
# rcParamsDefault, no need to reemit them here.
140+
with_api.suppress_matplotlib_deprecation_warning():
141+
# don't trigger RcParams.__getitem__('backend')
142+
style= {k:rcParamsDefault[k]forkinrcParamsDefault
143+
ifknotinSTYLE_BLACKLIST}
144+
elifstyleinlibrary:
145+
style=library[style]
146+
elif"."instyle:
147+
pkg,_,name=style.rpartition(".")
148+
try:
149+
path= (importlib_resources.files(pkg)
150+
/f"{name}.{STYLE_EXTENSION}")
151+
style=_rc_params_in_file(path)
152+
except (ModuleNotFoundError,IOError)asexc:
153+
# There is an ambiguity whether a dotted name refers to a
154+
# package.style_name or to a dotted file path. Currently,
155+
# we silently try the first form and then the second one;
156+
# in the future, we may consider forcing file paths to
157+
# either use Path objects or be prepended with "./" and use
158+
# the slash as marker for file paths.
159+
pass
160+
ifisinstance(style, (str,Path)):
151161
try:
152-
rc=rc_params_from_file(style,use_default_template=False)
153-
_apply_style(rc)
162+
style=_rc_params_in_file(style)
154163
exceptIOErroraserr:
155164
raiseIOError(
156-
"{!r} not found in the style library and input is not a "
157-
"valid URL or path; see `style.available` for list of "
158-
"available styles".format(style))fromerr
165+
f"{style!r} is not a valid package style, path of style "
166+
f"file, URL of style file, or library style name (library "
167+
f"styles are listed in `style.available`)")fromerr
168+
filtered= {}
169+
forkinstyle:# don't trigger RcParams.__getitem__('backend')
170+
ifkinSTYLE_BLACKLIST:
171+
_api.warn_external(
172+
f"Style includes a parameter,{k!r}, that is not "
173+
f"related to style. Ignoring this parameter.")
174+
else:
175+
filtered[k]=style[k]
176+
mpl.rcParams.update(filtered)
159177

160178

161179
@contextlib.contextmanager
@@ -205,8 +223,7 @@ def read_style_directory(style_dir):
205223
styles=dict()
206224
forpathinPath(style_dir).glob(f"*.{STYLE_EXTENSION}"):
207225
withwarnings.catch_warnings(record=True)aswarns:
208-
styles[path.stem]=rc_params_from_file(
209-
path,use_default_template=False)
226+
styles[path.stem]=_rc_params_in_file(path)
210227
forwinwarns:
211228
_log.warning('In %s: %s',path,w.message)
212229
returnstyles

‎lib/matplotlib/tests/test_style.py‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,3 +190,18 @@ def test_deprecated_seaborn_styles():
190190

191191
deftest_up_to_date_blacklist():
192192
assertmpl.style.core.STYLE_BLACKLIST<= {*mpl.rcsetup._validators}
193+
194+
195+
deftest_style_from_module(tmp_path,monkeypatch):
196+
monkeypatch.syspath_prepend(tmp_path)
197+
monkeypatch.chdir(tmp_path)
198+
pkg_path=tmp_path/"mpl_test_style_pkg"
199+
pkg_path.mkdir()
200+
(pkg_path/"test_style.mplstyle").write_text(
201+
"lines.linewidth: 42",encoding="utf-8")
202+
pkg_path.with_suffix(".mplstyle").write_text(
203+
"lines.linewidth: 84",encoding="utf-8")
204+
mpl.style.use("mpl_test_style_pkg.test_style")
205+
assertmpl.rcParams["lines.linewidth"]==42
206+
mpl.style.use("mpl_test_style_pkg.mplstyle")
207+
assertmpl.rcParams["lines.linewidth"]==84

‎requirements/testing/minver.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
contourpy==1.0.1
44
cycler==0.10
55
kiwisolver==1.0.1
6+
importlib-resources==3.2.0
67
numpy==1.19.0
78
packaging==20.0
89
pillow==6.2.1

‎setup.py‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,11 @@ def make_release_tree(self, base_dir, files):
334334
os.environ.get("CIBUILDWHEEL","0")!="1"
335335
)else []
336336
),
337+
extras_require={
338+
':python_version<"3.10"': [
339+
"importlib-resources>=3.2.0",
340+
],
341+
},
337342
use_scm_version={
338343
"version_scheme":"release-branch-semver",
339344
"local_scheme":"node-and-date",

‎tutorials/introductory/customizing.py‎

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
1010
There are three ways to customize Matplotlib:
1111
12-
1. :ref:`Setting rcParams at runtime<customizing-with-dynamic-rc-settings>`.
13-
2. :ref:`Using style sheets<customizing-with-style-sheets>`.
14-
3. :ref:`Changing your matplotlibrc file<customizing-with-matplotlibrc-files>`.
12+
1. :ref:`Setting rcParams at runtime<customizing-with-dynamic-rc-settings>`.
13+
2. :ref:`Using style sheets<customizing-with-style-sheets>`.
14+
3. :ref:`Changing your matplotlibrc file<customizing-with-matplotlibrc-files>`.
1515
1616
Setting rcParams at runtime takes precedence over style sheets, style
1717
sheets take precedence over :file:`matplotlibrc` files.
@@ -137,6 +137,17 @@ def plotting_function():
137137
# >>> import matplotlib.pyplot as plt
138138
# >>> plt.style.use('./images/presentation.mplstyle')
139139
#
140+
#
141+
# Distributing styles
142+
# -------------------
143+
#
144+
# You can include style sheets into standard importable Python packages (which
145+
# can be e.g. distributed on PyPI). If your package is importable as
146+
# ``import mypackage``, with a ``mypackage/__init__.py`` module, and you add
147+
# a ``mypackage/presentation.mplstyle`` style sheet, then it can be used as
148+
# ``plt.style.use("mypackage.presentation")``. Subpackages (e.g.
149+
# ``dotted.package.name``) are also supported.
150+
#
140151
# Alternatively, you can make your style known to Matplotlib by placing
141152
# your ``<style-name>.mplstyle`` file into ``mpl_configdir/stylelib``. You
142153
# can then load your custom style sheet with a call to

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp