Skip to content

Commit 2b6927d

Browse files
committed
Allow kwarg handles and labels figure.legend
Allow kwarg handles and labels figure.legend Small refactor of check for labels so it is inside legend.Legend attempt to refactor legend; not passing tests small typo Moved kwarg documentation out of child functions and into legend. Fixed documentation passthroughs so they work properly Fixed documentation passthroughs so they work properly Remerge master, small changes Fixed tests Remove repeated labels if same linestyle Remove repeated labels if same linestyle Removed ability of third positional argument for axes.legend Deprecate third psotionsal argument for fig.legend Allow parasite axes to call legend(): parasite_simple.py Fixed doc Fixed doc Added twinx test for legend merge fix merge fix Fixed legend handling of handles-only input; added error message Fixed legend handling of handles-only input for py27 Fixed small doc change MNT: do not special-case loc as positional arg Fixed small doc change Fix PEP8 and test error Fix PEP8 and test error
1 parent e10c523 commit 2b6927d

File tree

5 files changed

+753
-248
lines changed

5 files changed

+753
-248
lines changed

lib/matplotlib/axes/_axes.py

+16-79
Original file line numberDiff line numberDiff line change
@@ -252,27 +252,6 @@ def set_ylabel(self, ylabel, fontdict=None, labelpad=None, **kwargs):
252252
self.yaxis.labelpad = labelpad
253253
return self.yaxis.set_label_text(ylabel, fontdict, **kwargs)
254254

255-
def _get_legend_handles(self, legend_handler_map=None):
256-
"""
257-
Return a generator of artists that can be used as handles in
258-
a legend.
259-
260-
"""
261-
handles_original = (self.lines + self.patches +
262-
self.collections + self.containers)
263-
handler_map = mlegend.Legend.get_default_handler_map()
264-
265-
if legend_handler_map is not None:
266-
handler_map = handler_map.copy()
267-
handler_map.update(legend_handler_map)
268-
269-
has_handler = mlegend.Legend.get_legend_handler
270-
271-
for handle in handles_original:
272-
label = handle.get_label()
273-
if label != '_nolegend_' and has_handler(handler_map, handle):
274-
yield handle
275-
276255
def get_legend_handles_labels(self, legend_handler_map=None):
277256
"""
278257
Return handles and labels for legend
@@ -283,16 +262,13 @@ def get_legend_handles_labels(self, legend_handler_map=None):
283262
ax.legend(h, l)
284263
285264
"""
286-
handles = []
287-
labels = []
288-
for handle in self._get_legend_handles(legend_handler_map):
289-
label = handle.get_label()
290-
if label and not label.startswith('_'):
291-
handles.append(handle)
292-
labels.append(label)
293265

266+
# pass through to legend.
267+
handles, labels = mlegend._get_legend_handles_labels([self],
268+
legend_handler_map)
294269
return handles, labels
295270

271+
@docstring.dedent_interpd
296272
def legend(self, *args, **kwargs):
297273
"""
298274
Places a legend on the axes.
@@ -328,6 +304,7 @@ def legend(self, *args, **kwargs):
328304
329305
Parameters
330306
----------
307+
331308
loc : int or string or pair of floats, default: 'upper right'
332309
The location of the legend. Possible codes are:
333310
@@ -497,6 +474,11 @@ def legend(self, *args, **kwargs):
497474
handler. This `handler_map` updates the default handler map
498475
found at :func:`matplotlib.legend.Legend.get_legend_handler_map`.
499476
477+
Returns
478+
-------
479+
480+
:class:`matplotlib.legend.Legend` instance
481+
500482
Notes
501483
-----
502484
@@ -509,57 +491,12 @@ def legend(self, *args, **kwargs):
509491
.. plot:: gallery/api/legend.py
510492
511493
"""
512-
handlers = kwargs.get('handler_map', {}) or {}
513-
514-
# Support handles and labels being passed as keywords.
515-
handles = kwargs.pop('handles', None)
516-
labels = kwargs.pop('labels', None)
517-
518-
if (handles is not None or labels is not None) and len(args):
519-
warnings.warn("You have mixed positional and keyword "
520-
"arguments, some input will be "
521-
"discarded.")
522-
523-
# if got both handles and labels as kwargs, make same length
524-
if handles and labels:
525-
handles, labels = zip(*zip(handles, labels))
526-
527-
elif handles is not None and labels is None:
528-
labels = [handle.get_label() for handle in handles]
529-
for label, handle in zip(labels[:], handles[:]):
530-
if label.startswith('_'):
531-
warnings.warn('The handle {!r} has a label of {!r} which '
532-
'cannot be automatically added to the '
533-
'legend.'.format(handle, label))
534-
labels.remove(label)
535-
handles.remove(handle)
536-
537-
elif labels is not None and handles is None:
538-
# Get as many handles as there are labels.
539-
handles = [handle for handle, label
540-
in zip(self._get_legend_handles(handlers), labels)]
541-
542-
# No arguments - automatically detect labels and handles.
543-
elif len(args) == 0:
544-
handles, labels = self.get_legend_handles_labels(handlers)
545-
if not handles:
546-
return None
547-
548-
# One argument. User defined labels - automatic handle detection.
549-
elif len(args) == 1:
550-
labels, = args
551-
# Get as many handles as there are labels.
552-
handles = [handle for handle, label
553-
in zip(self._get_legend_handles(handlers), labels)]
554-
555-
# Two arguments:
556-
# * user defined handles and labels
557-
elif len(args) == 2:
558-
handles, labels = args
559-
560-
else:
561-
raise TypeError('Invalid arguments to legend.')
562-
494+
handles, labels, extra_args, kwargs = mlegend._parse_legend_args(
495+
[self],
496+
*args,
497+
**kwargs)
498+
if len(extra_args):
499+
raise TypeError('legend only accepts two non-keyword arguments')
563500
self.legend_ = mlegend.Legend(self, handles, labels, **kwargs)
564501
self.legend_._remove_method = lambda h: setattr(self, 'legend_', None)
565502
return self.legend_

0 commit comments

Comments
 (0)