Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a03498d

Browse files
authored
Merge branch 'matplotlib:main' into documentation_1
2 parents a89ef1f + 2c4f552 commit a03498d

25 files changed

+243
-170
lines changed

.github/codecov.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@ coverage:
2121
if_no_uploads: error
2222
if_not_found: success
2323
if_ci_failed: failure
24-
paths: '!lib/.*/tests/.*'
24+
paths:
25+
- '!lib/.*/tests/.*'
2526
tests:
2627
target: auto
2728
if_no_uploads: error
2829
if_not_found: success
2930
if_ci_failed: failure
30-
paths: 'lib/.*/tests/.*'
31+
paths:
32+
- 'lib/.*/tests/.*'

.github/workflows/mypy-stubtest.yml

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,35 @@ jobs:
2020

2121
- name: Install mypy
2222
run: |
23-
pip3 install -r requirements/testing/mypy.txt -r requirements/testing/all.txt
24-
pip3 install .
23+
pip3 install -r requirements/testing/mypy.txt \
24+
-r requirements/testing/all.txt
25+
pip3 install -e .
26+
27+
- name: Set up reviewdog
28+
run: |
29+
mkdir -p "$HOME/bin"
30+
curl -sfL \
31+
https://github.com/reviewdog/reviewdog/raw/master/install.sh | \
32+
sh -s -- -b "$HOME/bin"
33+
echo "$HOME/bin" >> $GITHUB_PATH
2534
2635
- name: Run mypy stubtest
36+
env:
37+
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
2738
run: |
28-
# the ignore missing imports can be removed when typed cycler is released and used
29-
MPLBACKEND=agg python -m mypy.stubtest matplotlib --mypy-config-file pyproject.toml \
30-
--allowlist ci/mypy-stubtest-allowlist.txt
39+
set -o pipefail
40+
MPLBACKEND=agg python -m mypy.stubtest \
41+
--mypy-config-file pyproject.toml \
42+
--allowlist ci/mypy-stubtest-allowlist.txt \
43+
matplotlib | \
44+
reviewdog \
45+
-efm '%Eerror: %m' \
46+
-efm '%CStub: in file %f:%l' \
47+
-efm '%CStub: in file %f' \
48+
-efm '%+CRuntime:%.%#' \
49+
-efm '%+CMISSING' \
50+
-efm '%+Cdef %.%#' \
51+
-efm '%+C<%.%#>' \
52+
-efm '%Z' \
53+
-reporter=github-check -tee -name=mypy-stubtest \
54+
-filter-mode=nofilter

azure-pipelines.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ pr:
1111
branches:
1212
exclude:
1313
- v*-doc
14+
paths:
15+
exclude:
16+
- doc/**/*
17+
- galleries/**/*
1418

1519
stages:
1620

doc/_static/mpl.css

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,11 @@ html[data-theme="dark"] .sphx-glr-thumbcontainer {
6262
padding: 0;
6363
}
6464

65-
/* hide note linking to the download section at the bottom of galleries
66-
* as suggested in https://github.com/sphinx-gallery/sphinx-gallery/issues/760
65+
/* hide download buttons in example headers
66+
* https://sphinx-gallery.github.io/stable/advanced.html#hide-the-download-buttons-in-the-example-headers
6767
*/
6868
div.sphx-glr-download-link-note {
69-
height: 0px;
70-
visibility: hidden;
69+
display: none;
7170
}
7271

7372
/* re-style the download button */
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Invalid types for Annotation xycoords now raise TypeError
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
Previously, a `RuntimeError` would be raised in some cases.

doc/devel/coding_guide.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,8 @@ will run on all supported platforms and versions of Python.
369369
individual commits by including the following substrings in commit messages:
370370

371371
- ``[ci doc]``: restrict the CI to documentation checks. For when you only
372-
changed documentation.
372+
changed documentation (this skip is automatic if the changes are only under
373+
``doc/`` or ``galleries/``).
373374
- ``[skip circle]``: skip the documentation build check. For when you didn't
374375
change documentation.
375376
- Unit tests can be turned off for individual platforms with
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
``Figure.get_suptitle()``, ``Figure.get_supxlabel()``, ``Figure.get_supylabel()``
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
These methods return the strings set by ``Figure.suptitle()``, ``Figure.supxlabel()``
4+
and ``Figure.supylabel()`` respectively.

lib/matplotlib/_api/__init__.py

Lines changed: 23 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -58,22 +58,20 @@ def fget(self):
5858
return self._fget
5959

6060

61-
# In the following check_foo() functions, the first parameter starts with an
62-
# underscore because it is intended to be positional-only (e.g., so that
63-
# `_api.check_isinstance([...], types=foo)` doesn't fail.
61+
# In the following check_foo() functions, the first parameter is positional-only to make
62+
# e.g. `_api.check_isinstance([...], types=foo)` work.
6463

65-
def check_isinstance(_types, **kwargs):
64+
def check_isinstance(types, /, **kwargs):
6665
"""
6766
For each *key, value* pair in *kwargs*, check that *value* is an instance
68-
of one of *_types*; if not, raise an appropriate TypeError.
67+
of one of *types*; if not, raise an appropriate TypeError.
6968
70-
As a special case, a ``None`` entry in *_types* is treated as NoneType.
69+
As a special case, a ``None`` entry in *types* is treated as NoneType.
7170
7271
Examples
7372
--------
7473
>>> _api.check_isinstance((SomeClass, None), arg=arg)
7574
"""
76-
types = _types
7775
none_type = type(None)
7876
types = ((types,) if isinstance(types, type) else
7977
(none_type,) if types is None else
@@ -98,31 +96,31 @@ def type_name(tp):
9896
type_name(type(v))))
9997

10098

101-
def check_in_list(_values, *, _print_supported_values=True, **kwargs):
99+
def check_in_list(values, /, *, _print_supported_values=True, **kwargs):
102100
"""
103-
For each *key, value* pair in *kwargs*, check that *value* is in *_values*.
101+
For each *key, value* pair in *kwargs*, check that *value* is in *values*;
102+
if not, raise an appropriate ValueError.
104103
105104
Parameters
106105
----------
107-
_values : iterable
106+
values : iterable
108107
Sequence of values to check on.
109108
_print_supported_values : bool, default: True
110-
Whether to print *_values* when raising ValueError.
109+
Whether to print *values* when raising ValueError.
111110
**kwargs : dict
112-
*key, value* pairs as keyword arguments to find in *_values*.
111+
*key, value* pairs as keyword arguments to find in *values*.
113112
114113
Raises
115114
------
116115
ValueError
117-
If any *value* in *kwargs* is not found in *_values*.
116+
If any *value* in *kwargs* is not found in *values*.
118117
119118
Examples
120119
--------
121120
>>> _api.check_in_list(["foo", "bar"], arg=arg, other_arg=other_arg)
122121
"""
123122
if not kwargs:
124123
raise TypeError("No argument to check!")
125-
values = _values
126124
for key, val in kwargs.items():
127125
if val not in values:
128126
msg = f"{val!r} is not a valid value for {key}"
@@ -131,10 +129,10 @@ def check_in_list(_values, *, _print_supported_values=True, **kwargs):
131129
raise ValueError(msg)
132130

133131

134-
def check_shape(_shape, **kwargs):
132+
def check_shape(shape, /, **kwargs):
135133
"""
136-
For each *key, value* pair in *kwargs*, check that *value* has the shape
137-
*_shape*, if not, raise an appropriate ValueError.
134+
For each *key, value* pair in *kwargs*, check that *value* has the shape *shape*;
135+
if not, raise an appropriate ValueError.
138136
139137
*None* in the shape is treated as a "free" size that can have any length.
140138
e.g. (None, 2) -> (N, 2)
@@ -147,42 +145,37 @@ def check_shape(_shape, **kwargs):
147145
148146
>>> _api.check_shape((None, 2), arg=arg, other_arg=other_arg)
149147
"""
150-
target_shape = _shape
151148
for k, v in kwargs.items():
152149
data_shape = v.shape
153150

154-
if len(target_shape) != len(data_shape) or any(
155-
t not in [s, None]
156-
for t, s in zip(target_shape, data_shape)
157-
):
151+
if (len(data_shape) != len(shape)
152+
or any(s != t and t is not None for s, t in zip(data_shape, shape))):
158153
dim_labels = iter(itertools.chain(
159154
'MNLIJKLH',
160155
(f"D{i}" for i in itertools.count())))
161156
text_shape = ", ".join(str(n)
162157
if n is not None
163158
else next(dim_labels)
164-
for n in target_shape)
165-
if len(target_shape) == 1:
159+
for n in shape)
160+
if len(shape) == 1:
166161
text_shape += ","
167162

168163
raise ValueError(
169-
f"{k!r} must be {len(target_shape)}D "
170-
f"with shape ({text_shape}). "
171-
f"Your input has shape {v.shape}."
164+
f"{k!r} must be {len(shape)}D with shape ({text_shape}), "
165+
f"but your input has shape {v.shape}"
172166
)
173167

174168

175-
def check_getitem(_mapping, **kwargs):
169+
def check_getitem(mapping, /, **kwargs):
176170
"""
177171
*kwargs* must consist of a single *key, value* pair. If *key* is in
178-
*_mapping*, return ``_mapping[value]``; else, raise an appropriate
172+
*mapping*, return ``mapping[value]``; else, raise an appropriate
179173
ValueError.
180174
181175
Examples
182176
--------
183177
>>> _api.check_getitem({"foo": "bar"}, arg=arg)
184178
"""
185-
mapping = _mapping
186179
if len(kwargs) != 1:
187180
raise ValueError("check_getitem takes a single keyword argument")
188181
(k, v), = kwargs.items()

lib/matplotlib/axes/_axes.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1313,9 +1313,6 @@ def eventplot(self, positions, orientation='horizontal', lineoffsets=1,
13131313
else:
13141314
positions = [np.asanyarray(positions)]
13151315

1316-
if len(positions) == 0:
1317-
return []
1318-
13191316
poss = []
13201317
for position in positions:
13211318
poss += self._process_unit_info([("x", position)], kwargs)
@@ -1345,13 +1342,15 @@ def eventplot(self, positions, orientation='horizontal', lineoffsets=1,
13451342
linewidths = np.asarray(linewidths)
13461343

13471344
if len(lineoffsets) == 0:
1348-
lineoffsets = [None]
1345+
raise ValueError('lineoffsets cannot be empty')
13491346
if len(linelengths) == 0:
1350-
linelengths = [None]
1351-
if len(linewidths) == 0:
1352-
lineoffsets = [None]
1347+
raise ValueError('linelengths cannot be empty')
1348+
if len(linestyles) == 0:
1349+
raise ValueError('linestyles cannot be empty')
13531350
if len(linewidths) == 0:
1354-
lineoffsets = [None]
1351+
raise ValueError('linewidths cannot be empty')
1352+
if len(alpha) == 0:
1353+
raise ValueError('alpha cannot be empty')
13551354
if len(colors) == 0:
13561355
colors = [None]
13571356
try:
@@ -2770,7 +2769,7 @@ def sign(x):
27702769
lambda r, b=bar:
27712770
mtransforms.Bbox.intersection(
27722771
b.get_window_extent(r), b.get_clip_box()
2773-
)
2772+
) or mtransforms.Bbox.null()
27742773
)
27752774
else: # edge
27762775
if orientation == "vertical":

lib/matplotlib/figure.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,11 @@ def suptitle(self, t, **kwargs):
388388
'size': 'figure.titlesize', 'weight': 'figure.titleweight'}
389389
return self._suplabels(t, info, **kwargs)
390390

391+
def get_suptitle(self):
392+
"""Return the suptitle as string or an empty string if not set."""
393+
text_obj = self._suptitle
394+
return "" if text_obj is None else text_obj.get_text()
395+
391396
@_docstring.Substitution(x0=0.5, y0=0.01, name='supxlabel', ha='center',
392397
va='bottom', rc='label')
393398
@_docstring.copy(_suplabels)
@@ -398,6 +403,11 @@ def supxlabel(self, t, **kwargs):
398403
'size': 'figure.labelsize', 'weight': 'figure.labelweight'}
399404
return self._suplabels(t, info, **kwargs)
400405

406+
def get_supxlabel(self):
407+
"""Return the supxlabel as string or an empty string if not set."""
408+
text_obj = self._supxlabel
409+
return "" if text_obj is None else text_obj.get_text()
410+
401411
@_docstring.Substitution(x0=0.02, y0=0.5, name='supylabel', ha='left',
402412
va='center', rc='label')
403413
@_docstring.copy(_suplabels)
@@ -409,6 +419,11 @@ def supylabel(self, t, **kwargs):
409419
'weight': 'figure.labelweight'}
410420
return self._suplabels(t, info, **kwargs)
411421

422+
def get_supylabel(self):
423+
"""Return the supylabel as string or an empty string if not set."""
424+
text_obj = self._supylabel
425+
return "" if text_obj is None else text_obj.get_text()
426+
412427
def get_edgecolor(self):
413428
"""Get the edge color of the Figure rectangle."""
414429
return self.patch.get_edgecolor()

lib/matplotlib/figure.pyi

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,11 @@ class FigureBase(Artist):
9090
def get_children(self) -> list[Artist]: ...
9191
def contains(self, mouseevent: MouseEvent) -> tuple[bool, dict[Any, Any]]: ...
9292
def suptitle(self, t: str, **kwargs) -> Text: ...
93+
def get_suptitle(self) -> str: ...
9394
def supxlabel(self, t: str, **kwargs) -> Text: ...
95+
def get_supxlabel(self) -> str: ...
9496
def supylabel(self, t: str, **kwargs) -> Text: ...
97+
def get_supylabel(self) -> str: ...
9598
def get_edgecolor(self) -> ColorType: ...
9699
def get_facecolor(self) -> ColorType: ...
97100
def get_frameon(self) -> bool: ...

lib/matplotlib/offsetbox.py

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1400,19 +1400,9 @@ def get_tightbbox(self, renderer=None):
14001400
for child in self.get_children()])
14011401

14021402
def update_positions(self, renderer):
1403-
"""
1404-
Update pixel positions for the annotated point, the text and the arrow.
1405-
"""
1406-
1407-
x, y = self.xybox
1408-
if isinstance(self.boxcoords, tuple):
1409-
xcoord, ycoord = self.boxcoords
1410-
x1, y1 = self._get_xy(renderer, x, y, xcoord)
1411-
x2, y2 = self._get_xy(renderer, x, y, ycoord)
1412-
ox0, oy0 = x1, y2
1413-
else:
1414-
ox0, oy0 = self._get_xy(renderer, x, y, self.boxcoords)
1403+
"""Update pixel positions for the annotated point, the text, and the arrow."""
14151404

1405+
ox0, oy0 = self._get_xy(renderer, self.xybox, self.boxcoords)
14161406
bbox = self.offsetbox.get_bbox(renderer)
14171407
fw, fh = self._box_alignment
14181408
self.offsetbox.set_offset(

0 commit comments

Comments
 (0)