test_legend.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  1. import collections
  2. import platform
  3. from unittest import mock
  4. import numpy as np
  5. import pytest
  6. from matplotlib.testing.decorators import image_comparison
  7. import matplotlib.pyplot as plt
  8. import matplotlib as mpl
  9. import matplotlib.transforms as mtransforms
  10. import matplotlib.collections as mcollections
  11. from matplotlib.legend_handler import HandlerTuple
  12. import matplotlib.legend as mlegend
  13. from matplotlib.cbook.deprecation import MatplotlibDeprecationWarning
  14. from matplotlib import rc_context
  15. def test_legend_ordereddict():
  16. # smoketest that ordereddict inputs work...
  17. X = np.random.randn(10)
  18. Y = np.random.randn(10)
  19. labels = ['a'] * 5 + ['b'] * 5
  20. colors = ['r'] * 5 + ['g'] * 5
  21. fig, ax = plt.subplots()
  22. for x, y, label, color in zip(X, Y, labels, colors):
  23. ax.scatter(x, y, label=label, c=color)
  24. handles, labels = ax.get_legend_handles_labels()
  25. legend = collections.OrderedDict(zip(labels, handles))
  26. ax.legend(legend.values(), legend.keys(),
  27. loc='center left', bbox_to_anchor=(1, .5))
  28. @image_comparison(['legend_auto1'], remove_text=True)
  29. def test_legend_auto1():
  30. 'Test automatic legend placement'
  31. fig = plt.figure()
  32. ax = fig.add_subplot(111)
  33. x = np.arange(100)
  34. ax.plot(x, 50 - x, 'o', label='y=1')
  35. ax.plot(x, x - 50, 'o', label='y=-1')
  36. ax.legend(loc='best')
  37. @image_comparison(['legend_auto2'], remove_text=True)
  38. def test_legend_auto2():
  39. 'Test automatic legend placement'
  40. fig = plt.figure()
  41. ax = fig.add_subplot(111)
  42. x = np.arange(100)
  43. b1 = ax.bar(x, x, align='edge', color='m')
  44. b2 = ax.bar(x, x[::-1], align='edge', color='g')
  45. ax.legend([b1[0], b2[0]], ['up', 'down'], loc='best')
  46. @image_comparison(['legend_auto3'])
  47. def test_legend_auto3():
  48. 'Test automatic legend placement'
  49. fig = plt.figure()
  50. ax = fig.add_subplot(111)
  51. x = [0.9, 0.1, 0.1, 0.9, 0.9, 0.5]
  52. y = [0.95, 0.95, 0.05, 0.05, 0.5, 0.5]
  53. ax.plot(x, y, 'o-', label='line')
  54. ax.set_xlim(0.0, 1.0)
  55. ax.set_ylim(0.0, 1.0)
  56. ax.legend(loc='best')
  57. @image_comparison(['legend_various_labels'], remove_text=True)
  58. def test_various_labels():
  59. # tests all sorts of label types
  60. fig = plt.figure()
  61. ax = fig.add_subplot(121)
  62. ax.plot(np.arange(4), 'o', label=1)
  63. ax.plot(np.linspace(4, 4.1), 'o', label='Développés')
  64. ax.plot(np.arange(4, 1, -1), 'o', label='__nolegend__')
  65. ax.legend(numpoints=1, loc='best')
  66. @image_comparison(['legend_labels_first.png'], remove_text=True)
  67. def test_labels_first():
  68. # test labels to left of markers
  69. fig = plt.figure()
  70. ax = fig.add_subplot(111)
  71. ax.plot(np.arange(10), '-o', label=1)
  72. ax.plot(np.ones(10)*5, ':x', label="x")
  73. ax.plot(np.arange(20, 10, -1), 'd', label="diamond")
  74. ax.legend(loc='best', markerfirst=False)
  75. @image_comparison(['legend_multiple_keys.png'], remove_text=True)
  76. def test_multiple_keys():
  77. # test legend entries with multiple keys
  78. fig = plt.figure()
  79. ax = fig.add_subplot(111)
  80. p1, = ax.plot([1, 2, 3], '-o')
  81. p2, = ax.plot([2, 3, 4], '-x')
  82. p3, = ax.plot([3, 4, 5], '-d')
  83. ax.legend([(p1, p2), (p2, p1), p3], ['two keys', 'pad=0', 'one key'],
  84. numpoints=1,
  85. handler_map={(p1, p2): HandlerTuple(ndivide=None),
  86. (p2, p1): HandlerTuple(ndivide=None, pad=0)})
  87. @image_comparison(['rgba_alpha.png'], remove_text=True,
  88. tol={'aarch64': 0.02}.get(platform.machine(), 0.0))
  89. def test_alpha_rgba():
  90. import matplotlib.pyplot as plt
  91. fig, ax = plt.subplots(1, 1)
  92. ax.plot(range(10), lw=5)
  93. leg = plt.legend(['Longlabel that will go away'], loc='center')
  94. leg.legendPatch.set_facecolor([1, 0, 0, 0.5])
  95. @image_comparison(['rcparam_alpha.png'], remove_text=True,
  96. tol={'aarch64': 0.02}.get(platform.machine(), 0.0))
  97. def test_alpha_rcparam():
  98. import matplotlib.pyplot as plt
  99. fig, ax = plt.subplots(1, 1)
  100. ax.plot(range(10), lw=5)
  101. with mpl.rc_context(rc={'legend.framealpha': .75}):
  102. leg = plt.legend(['Longlabel that will go away'], loc='center')
  103. # this alpha is going to be over-ridden by the rcparam with
  104. # sets the alpha of the patch to be non-None which causes the alpha
  105. # value of the face color to be discarded. This behavior may not be
  106. # ideal, but it is what it is and we should keep track of it changing
  107. leg.legendPatch.set_facecolor([1, 0, 0, 0.5])
  108. @image_comparison(['fancy'], remove_text=True)
  109. def test_fancy():
  110. # using subplot triggers some offsetbox functionality untested elsewhere
  111. plt.subplot(121)
  112. plt.scatter(np.arange(10), np.arange(10, 0, -1), label='XX\nXX')
  113. plt.plot([5] * 10, 'o--', label='XX')
  114. plt.errorbar(np.arange(10), np.arange(10), xerr=0.5,
  115. yerr=0.5, label='XX')
  116. plt.legend(loc="center left", bbox_to_anchor=[1.0, 0.5],
  117. ncol=2, shadow=True, title="My legend", numpoints=1)
  118. @image_comparison(['framealpha'], remove_text=True,
  119. tol={'aarch64': 0.02}.get(platform.machine(), 0.0))
  120. def test_framealpha():
  121. x = np.linspace(1, 100, 100)
  122. y = x
  123. plt.plot(x, y, label='mylabel', lw=10)
  124. plt.legend(framealpha=0.5)
  125. @image_comparison(['scatter_rc3', 'scatter_rc1'], remove_text=True)
  126. def test_rc():
  127. # using subplot triggers some offsetbox functionality untested elsewhere
  128. plt.figure()
  129. ax = plt.subplot(121)
  130. ax.scatter(np.arange(10), np.arange(10, 0, -1), label='three')
  131. ax.legend(loc="center left", bbox_to_anchor=[1.0, 0.5],
  132. title="My legend")
  133. mpl.rcParams['legend.scatterpoints'] = 1
  134. plt.figure()
  135. ax = plt.subplot(121)
  136. ax.scatter(np.arange(10), np.arange(10, 0, -1), label='one')
  137. ax.legend(loc="center left", bbox_to_anchor=[1.0, 0.5],
  138. title="My legend")
  139. @image_comparison(['legend_expand'], remove_text=True)
  140. def test_legend_expand():
  141. 'Test expand mode'
  142. legend_modes = [None, "expand"]
  143. fig, axes_list = plt.subplots(len(legend_modes), 1)
  144. x = np.arange(100)
  145. for ax, mode in zip(axes_list, legend_modes):
  146. ax.plot(x, 50 - x, 'o', label='y=1')
  147. l1 = ax.legend(loc='upper left', mode=mode)
  148. ax.add_artist(l1)
  149. ax.plot(x, x - 50, 'o', label='y=-1')
  150. l2 = ax.legend(loc='right', mode=mode)
  151. ax.add_artist(l2)
  152. ax.legend(loc='lower left', mode=mode, ncol=2)
  153. @image_comparison(['hatching'], remove_text=True, style='default')
  154. def test_hatching():
  155. # Remove this line when this test image is regenerated.
  156. plt.rcParams['text.kerning_factor'] = 6
  157. fig, ax = plt.subplots()
  158. # Patches
  159. patch = plt.Rectangle((0, 0), 0.3, 0.3, hatch='xx',
  160. label='Patch\ndefault color\nfilled')
  161. ax.add_patch(patch)
  162. patch = plt.Rectangle((0.33, 0), 0.3, 0.3, hatch='||', edgecolor='C1',
  163. label='Patch\nexplicit color\nfilled')
  164. ax.add_patch(patch)
  165. patch = plt.Rectangle((0, 0.4), 0.3, 0.3, hatch='xx', fill=False,
  166. label='Patch\ndefault color\nunfilled')
  167. ax.add_patch(patch)
  168. patch = plt.Rectangle((0.33, 0.4), 0.3, 0.3, hatch='||', fill=False,
  169. edgecolor='C1',
  170. label='Patch\nexplicit color\nunfilled')
  171. ax.add_patch(patch)
  172. # Paths
  173. ax.fill_between([0, .15, .3], [.8, .8, .8], [.9, 1.0, .9],
  174. hatch='+', label='Path\ndefault color')
  175. ax.fill_between([.33, .48, .63], [.8, .8, .8], [.9, 1.0, .9],
  176. hatch='+', edgecolor='C2', label='Path\nexplicit color')
  177. ax.set_xlim(-0.01, 1.1)
  178. ax.set_ylim(-0.01, 1.1)
  179. ax.legend(handlelength=4, handleheight=4)
  180. def test_legend_remove():
  181. fig = plt.figure()
  182. ax = fig.add_subplot(1, 1, 1)
  183. lines = ax.plot(range(10))
  184. leg = fig.legend(lines, "test")
  185. leg.remove()
  186. assert fig.legends == []
  187. leg = ax.legend("test")
  188. leg.remove()
  189. assert ax.get_legend() is None
  190. class TestLegendFunction:
  191. # Tests the legend function on the Axes and pyplot.
  192. def test_legend_handle_label(self):
  193. lines = plt.plot(range(10))
  194. with mock.patch('matplotlib.legend.Legend') as Legend:
  195. plt.legend(lines, ['hello world'])
  196. Legend.assert_called_with(plt.gca(), lines, ['hello world'])
  197. def test_legend_no_args(self):
  198. lines = plt.plot(range(10), label='hello world')
  199. with mock.patch('matplotlib.legend.Legend') as Legend:
  200. plt.legend()
  201. Legend.assert_called_with(plt.gca(), lines, ['hello world'])
  202. def test_legend_label_args(self):
  203. lines = plt.plot(range(10), label='hello world')
  204. with mock.patch('matplotlib.legend.Legend') as Legend:
  205. plt.legend(['foobar'])
  206. Legend.assert_called_with(plt.gca(), lines, ['foobar'])
  207. def test_legend_three_args(self):
  208. lines = plt.plot(range(10), label='hello world')
  209. with mock.patch('matplotlib.legend.Legend') as Legend:
  210. plt.legend(lines, ['foobar'], loc='right')
  211. Legend.assert_called_with(plt.gca(), lines, ['foobar'], loc='right')
  212. def test_legend_handler_map(self):
  213. lines = plt.plot(range(10), label='hello world')
  214. with mock.patch('matplotlib.legend.'
  215. '_get_legend_handles_labels') as handles_labels:
  216. handles_labels.return_value = lines, ['hello world']
  217. plt.legend(handler_map={'1': 2})
  218. handles_labels.assert_called_with([plt.gca()], {'1': 2})
  219. def test_kwargs(self):
  220. fig, ax = plt.subplots(1, 1)
  221. th = np.linspace(0, 2*np.pi, 1024)
  222. lns, = ax.plot(th, np.sin(th), label='sin', lw=5)
  223. lnc, = ax.plot(th, np.cos(th), label='cos', lw=5)
  224. with mock.patch('matplotlib.legend.Legend') as Legend:
  225. ax.legend(labels=('a', 'b'), handles=(lnc, lns))
  226. Legend.assert_called_with(ax, (lnc, lns), ('a', 'b'))
  227. def test_warn_args_kwargs(self):
  228. fig, ax = plt.subplots(1, 1)
  229. th = np.linspace(0, 2*np.pi, 1024)
  230. lns, = ax.plot(th, np.sin(th), label='sin', lw=5)
  231. lnc, = ax.plot(th, np.cos(th), label='cos', lw=5)
  232. with pytest.warns(UserWarning) as record:
  233. ax.legend((lnc, lns), labels=('a', 'b'))
  234. assert len(record) == 1
  235. assert str(record[0].message) == (
  236. "You have mixed positional and keyword arguments, some input may "
  237. "be discarded.")
  238. def test_parasite(self):
  239. from mpl_toolkits.axes_grid1 import host_subplot
  240. host = host_subplot(111)
  241. par = host.twinx()
  242. p1, = host.plot([0, 1, 2], [0, 1, 2], label="Density")
  243. p2, = par.plot([0, 1, 2], [0, 3, 2], label="Temperature")
  244. with mock.patch('matplotlib.legend.Legend') as Legend:
  245. plt.legend()
  246. Legend.assert_called_with(host, [p1, p2], ['Density', 'Temperature'])
  247. class TestLegendFigureFunction:
  248. # Tests the legend function for figure
  249. def test_legend_handle_label(self):
  250. fig, ax = plt.subplots()
  251. lines = ax.plot(range(10))
  252. with mock.patch('matplotlib.legend.Legend') as Legend:
  253. fig.legend(lines, ['hello world'])
  254. Legend.assert_called_with(fig, lines, ['hello world'])
  255. def test_legend_no_args(self):
  256. fig, ax = plt.subplots()
  257. lines = ax.plot(range(10), label='hello world')
  258. with mock.patch('matplotlib.legend.Legend') as Legend:
  259. fig.legend()
  260. Legend.assert_called_with(fig, lines, ['hello world'])
  261. def test_legend_label_arg(self):
  262. fig, ax = plt.subplots()
  263. lines = ax.plot(range(10))
  264. with mock.patch('matplotlib.legend.Legend') as Legend:
  265. fig.legend(['foobar'])
  266. Legend.assert_called_with(fig, lines, ['foobar'])
  267. def test_legend_label_three_args(self):
  268. fig, ax = plt.subplots()
  269. lines = ax.plot(range(10))
  270. with mock.patch('matplotlib.legend.Legend') as Legend:
  271. fig.legend(lines, ['foobar'], 'right')
  272. Legend.assert_called_with(fig, lines, ['foobar'], 'right')
  273. def test_legend_label_three_args_pluskw(self):
  274. # test that third argument and loc= called together give
  275. # Exception
  276. fig, ax = plt.subplots()
  277. lines = ax.plot(range(10))
  278. with pytest.raises(Exception):
  279. fig.legend(lines, ['foobar'], 'right', loc='left')
  280. def test_legend_kw_args(self):
  281. fig, axs = plt.subplots(1, 2)
  282. lines = axs[0].plot(range(10))
  283. lines2 = axs[1].plot(np.arange(10) * 2.)
  284. with mock.patch('matplotlib.legend.Legend') as Legend:
  285. fig.legend(loc='right', labels=('a', 'b'),
  286. handles=(lines, lines2))
  287. Legend.assert_called_with(fig, (lines, lines2), ('a', 'b'),
  288. loc='right')
  289. def test_warn_args_kwargs(self):
  290. fig, axs = plt.subplots(1, 2)
  291. lines = axs[0].plot(range(10))
  292. lines2 = axs[1].plot(np.arange(10) * 2.)
  293. with pytest.warns(UserWarning) as record:
  294. fig.legend((lines, lines2), labels=('a', 'b'))
  295. assert len(record) == 1
  296. assert str(record[0].message) == (
  297. "You have mixed positional and keyword arguments, some input may "
  298. "be discarded.")
  299. @image_comparison(['legend_stackplot.png'])
  300. def test_legend_stackplot():
  301. '''test legend for PolyCollection using stackplot'''
  302. # related to #1341, #1943, and PR #3303
  303. fig = plt.figure()
  304. ax = fig.add_subplot(111)
  305. x = np.linspace(0, 10, 10)
  306. y1 = 1.0 * x
  307. y2 = 2.0 * x + 1
  308. y3 = 3.0 * x + 2
  309. ax.stackplot(x, y1, y2, y3, labels=['y1', 'y2', 'y3'])
  310. ax.set_xlim((0, 10))
  311. ax.set_ylim((0, 70))
  312. ax.legend(loc='best')
  313. def test_cross_figure_patch_legend():
  314. fig, ax = plt.subplots()
  315. fig2, ax2 = plt.subplots()
  316. brs = ax.bar(range(3), range(3))
  317. fig2.legend(brs, 'foo')
  318. def test_nanscatter():
  319. fig, ax = plt.subplots()
  320. h = ax.scatter([np.nan], [np.nan], marker="o",
  321. facecolor="r", edgecolor="r", s=3)
  322. ax.legend([h], ["scatter"])
  323. fig, ax = plt.subplots()
  324. for color in ['red', 'green', 'blue']:
  325. n = 750
  326. x, y = np.random.rand(2, n)
  327. scale = 200.0 * np.random.rand(n)
  328. ax.scatter(x, y, c=color, s=scale, label=color,
  329. alpha=0.3, edgecolors='none')
  330. ax.legend()
  331. ax.grid(True)
  332. def test_legend_repeatcheckok():
  333. fig, ax = plt.subplots()
  334. ax.scatter(0.0, 1.0, color='k', marker='o', label='test')
  335. ax.scatter(0.5, 0.0, color='r', marker='v', label='test')
  336. ax.legend()
  337. hand, lab = mlegend._get_legend_handles_labels([ax])
  338. assert len(lab) == 2
  339. fig, ax = plt.subplots()
  340. ax.scatter(0.0, 1.0, color='k', marker='o', label='test')
  341. ax.scatter(0.5, 0.0, color='k', marker='v', label='test')
  342. ax.legend()
  343. hand, lab = mlegend._get_legend_handles_labels([ax])
  344. assert len(lab) == 2
  345. @image_comparison(['not_covering_scatter.png'])
  346. def test_not_covering_scatter():
  347. colors = ['b', 'g', 'r']
  348. for n in range(3):
  349. plt.scatter([n], [n], color=colors[n])
  350. plt.legend(['foo', 'foo', 'foo'], loc='best')
  351. plt.gca().set_xlim(-0.5, 2.2)
  352. plt.gca().set_ylim(-0.5, 2.2)
  353. @image_comparison(['not_covering_scatter_transform.png'])
  354. def test_not_covering_scatter_transform():
  355. # Offsets point to top left, the default auto position
  356. offset = mtransforms.Affine2D().translate(-20, 20)
  357. x = np.linspace(0, 30, 1000)
  358. plt.plot(x, x)
  359. plt.scatter([20], [10], transform=offset + plt.gca().transData)
  360. plt.legend(['foo', 'bar'], loc='best')
  361. def test_linecollection_scaled_dashes():
  362. lines1 = [[(0, .5), (.5, 1)], [(.3, .6), (.2, .2)]]
  363. lines2 = [[[0.7, .2], [.8, .4]], [[.5, .7], [.6, .1]]]
  364. lines3 = [[[0.6, .2], [.8, .4]], [[.5, .7], [.1, .1]]]
  365. lc1 = mcollections.LineCollection(lines1, linestyles="--", lw=3)
  366. lc2 = mcollections.LineCollection(lines2, linestyles="-.")
  367. lc3 = mcollections.LineCollection(lines3, linestyles=":", lw=.5)
  368. fig, ax = plt.subplots()
  369. ax.add_collection(lc1)
  370. ax.add_collection(lc2)
  371. ax.add_collection(lc3)
  372. leg = ax.legend([lc1, lc2, lc3], ["line1", "line2", 'line 3'])
  373. h1, h2, h3 = leg.legendHandles
  374. for oh, lh in zip((lc1, lc2, lc3), (h1, h2, h3)):
  375. assert oh.get_linestyles()[0][1] == lh._dashSeq
  376. assert oh.get_linestyles()[0][0] == lh._dashOffset
  377. def test_handler_numpoints():
  378. """Test legend handler with numpoints <= 1."""
  379. # related to #6921 and PR #8478
  380. fig, ax = plt.subplots()
  381. ax.plot(range(5), label='test')
  382. ax.legend(numpoints=0.5)
  383. def test_empty_bar_chart_with_legend():
  384. """Test legend when bar chart is empty with a label."""
  385. # related to issue #13003. Calling plt.legend() should not
  386. # raise an IndexError.
  387. plt.bar([], [], label='test')
  388. plt.legend()
  389. def test_shadow_framealpha():
  390. # Test if framealpha is activated when shadow is True
  391. # and framealpha is not explicitly passed'''
  392. fig, ax = plt.subplots()
  393. ax.plot(range(100), label="test")
  394. leg = ax.legend(shadow=True, facecolor='w')
  395. assert leg.get_frame().get_alpha() == 1
  396. def test_legend_title_empty():
  397. # test that if we don't set the legend title, that
  398. # it comes back as an empty string, and that it is not
  399. # visible:
  400. fig, ax = plt.subplots()
  401. ax.plot(range(10))
  402. leg = ax.legend()
  403. assert leg.get_title().get_text() == ""
  404. assert not leg.get_title().get_visible()
  405. def test_legend_proper_window_extent():
  406. # test that legend returns the expected extent under various dpi...
  407. fig, ax = plt.subplots(dpi=100)
  408. ax.plot(range(10), label='Aardvark')
  409. leg = ax.legend()
  410. x01 = leg.get_window_extent(fig.canvas.get_renderer()).x0
  411. fig, ax = plt.subplots(dpi=200)
  412. ax.plot(range(10), label='Aardvark')
  413. leg = ax.legend()
  414. x02 = leg.get_window_extent(fig.canvas.get_renderer()).x0
  415. assert pytest.approx(x01*2, 0.1) == x02
  416. def test_window_extent_cached_renderer():
  417. fig, ax = plt.subplots(dpi=100)
  418. ax.plot(range(10), label='Aardvark')
  419. leg = ax.legend()
  420. leg2 = fig.legend()
  421. fig.canvas.draw()
  422. # check that get_window_extent will use the cached renderer
  423. leg.get_window_extent()
  424. leg2.get_window_extent()
  425. def test_legend_title_fontsize():
  426. # test the title_fontsize kwarg
  427. fig, ax = plt.subplots()
  428. ax.plot(range(10))
  429. leg = ax.legend(title='Aardvark', title_fontsize=22)
  430. assert leg.get_title().get_fontsize() == 22
  431. def test_get_set_draggable():
  432. legend = plt.legend()
  433. assert not legend.get_draggable()
  434. legend.set_draggable(True)
  435. assert legend.get_draggable()
  436. legend.set_draggable(False)
  437. assert not legend.get_draggable()
  438. def test_alpha_handles():
  439. x, n, hh = plt.hist([1, 2, 3], alpha=0.25, label='data', color='red')
  440. legend = plt.legend()
  441. for lh in legend.legendHandles:
  442. lh.set_alpha(1.0)
  443. assert lh.get_facecolor()[:-1] == hh[1].get_facecolor()[:-1]
  444. assert lh.get_edgecolor()[:-1] == hh[1].get_edgecolor()[:-1]
  445. def test_warn_big_data_best_loc():
  446. fig, ax = plt.subplots()
  447. fig.canvas.draw() # So that we can call draw_artist later.
  448. for idx in range(1000):
  449. ax.plot(np.arange(5000), label=idx)
  450. with rc_context({'legend.loc': 'best'}):
  451. legend = ax.legend()
  452. with pytest.warns(UserWarning) as records:
  453. fig.draw_artist(legend) # Don't bother drawing the lines -- it's slow.
  454. # The _find_best_position method of Legend is called twice, duplicating
  455. # the warning message.
  456. assert len(records) == 2
  457. for record in records:
  458. assert str(record.message) == (
  459. 'Creating legend with loc="best" can be slow with large '
  460. 'amounts of data.')
  461. def test_no_warn_big_data_when_loc_specified():
  462. fig, ax = plt.subplots()
  463. fig.canvas.draw()
  464. for idx in range(1000):
  465. ax.plot(np.arange(5000), label=idx)
  466. legend = ax.legend('best')
  467. with pytest.warns(None) as records:
  468. fig.draw_artist(legend)
  469. assert len(records) == 0