Skip to content

Commit 0b0f279

Browse files
committed
Better error messages in SVG backend for Keywords metadata
1 parent f8ab952 commit 0b0f279

File tree

2 files changed

+47
-12
lines changed

2 files changed

+47
-12
lines changed

lib/matplotlib/backends/backend_svg.py

+21-12
Original file line numberDiff line numberDiff line change
@@ -376,14 +376,14 @@ def _write_metadata(self, metadata):
376376
elif isinstance(d, (datetime.datetime, datetime.date)):
377377
dates.append(d.isoformat())
378378
else:
379-
raise ValueError(
379+
raise TypeError(
380380
'Invalid type for Date metadata. '
381381
'Expected iterable of str, date, or datetime, '
382382
'not {!r}.'.format(type(d)))
383383
else:
384-
raise ValueError('Invalid type for Date metadata. '
385-
'Expected str, date, datetime, or iterable '
386-
'of the same, not {!r}.'.format(type(date)))
384+
raise TypeError('Invalid type for Date metadata. '
385+
'Expected str, date, datetime, or iterable '
386+
'of the same, not {!r}.'.format(type(date)))
387387
metadata['Date'] = '/'.join(dates)
388388
elif 'Date' not in metadata:
389389
# Do not add `Date` if the user explicitly set `Date` to `None`
@@ -444,14 +444,23 @@ def ensure_metadata(mid):
444444
if keywords is not None:
445445
if isinstance(keywords, str):
446446
keywords = [keywords]
447-
448-
mid = ensure_metadata(mid)
449-
writer.start('dc:subject')
450-
writer.start('rdf:Bag')
451-
for keyword in keywords:
452-
writer.element('rdf:li', text=keyword)
453-
writer.end('rdf:Bag')
454-
writer.end('dc:subject')
447+
if np.iterable(keywords):
448+
mid = ensure_metadata(mid)
449+
writer.start('dc:subject')
450+
writer.start('rdf:Bag')
451+
for keyword in keywords:
452+
if isinstance(keyword, str):
453+
writer.element('rdf:li', text=keyword)
454+
else:
455+
raise TypeError('Invalid type for Keywords metadata. '
456+
'Expected iterable of str'
457+
', not {!r}.'.format(type(keyword)))
458+
writer.end('rdf:Bag')
459+
writer.end('dc:subject')
460+
else:
461+
raise TypeError('Invalid type for Keywords metadata. '
462+
'Expected str or iterable '
463+
'of str, not {!r}.'.format(type(keywords)))
455464

456465
if mid is not None:
457466
writer.close(mid)

lib/matplotlib/tests/test_backend_svg.py

+26
Original file line numberDiff line numberDiff line change
@@ -469,3 +469,29 @@ def test_svg_metadata():
469469
values = [node.text for node in
470470
rdf.findall(f'./{CCNS}Work/{DCNS}subject/{RDFNS}Bag/{RDFNS}li')]
471471
assert values == metadata['Keywords']
472+
473+
474+
@pytest.mark.parametrize('metadata,error,message', [
475+
({'Date': 1}, TypeError, "Invalid type for Date metadata. Expected str"),
476+
({'Date': [1]}, TypeError,
477+
"Invalid type for Date metadata. Expected iterable"),
478+
({'Keywords': 1}, TypeError,
479+
"Invalid type for Keywords metadata. Expected str"),
480+
({'Keywords': [1]}, TypeError,
481+
"Invalid type for Keywords metadata. Expected iterable"),
482+
({'Foo': 'Bar'}, ValueError, "Unknown metadata key"),
483+
])
484+
def test_svg_incorrect_metadata(metadata, error, message):
485+
with pytest.raises(error, match=message), BytesIO() as fd:
486+
fig, ax = plt.subplots()
487+
fig.savefig(fd, format='svg', metadata=metadata)
488+
489+
490+
def test_svg_escape():
491+
fig, ax = plt.subplots()
492+
fig.text(0.5, 0.5, "<\'\"&>", gid="<\'\"&>")
493+
ax.set_axis_off()
494+
with BytesIO() as fd:
495+
fig.savefig(fd, format='svg')
496+
buf = fd.getvalue().decode()
497+
assert '&lt;&apos;&quot;&amp;&gt;"' in buf

0 commit comments

Comments
 (0)