Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1""" 

2The rcsetup module contains the default values and the validation code for 

3customization using matplotlib's rc settings. 

4 

5Each rc setting is assigned a default value and a function used to validate 

6any attempted changes to that setting. The default values and validation 

7functions are defined in the rcsetup module, and are used to construct the 

8rcParams global object which stores the settings and is referenced throughout 

9matplotlib. 

10 

11These default values should be consistent with the default matplotlibrc file 

12that actually reflects the values given here. Any additions or deletions to the 

13parameter set listed here should also be visited to the 

14:file:`matplotlibrc.template` in matplotlib's root source directory. 

15""" 

16 

17from collections.abc import Iterable, Mapping 

18from functools import partial, reduce 

19import logging 

20import operator 

21import os 

22import re 

23 

24import matplotlib as mpl 

25from matplotlib import cbook 

26from matplotlib.cbook import ls_mapper 

27from matplotlib.fontconfig_pattern import parse_fontconfig_pattern 

28from matplotlib.colors import is_color_like 

29 

30# Don't let the original cycler collide with our validating cycler 

31from cycler import Cycler, cycler as ccycler 

32 

33 

34_log = logging.getLogger(__name__) 

35# The capitalized forms are needed for ipython at present; this may 

36# change for later versions. 

37interactive_bk = ['GTK3Agg', 'GTK3Cairo', 

38 'MacOSX', 

39 'nbAgg', 

40 'Qt4Agg', 'Qt4Cairo', 'Qt5Agg', 'Qt5Cairo', 

41 'TkAgg', 'TkCairo', 

42 'WebAgg', 

43 'WX', 'WXAgg', 'WXCairo'] 

44non_interactive_bk = ['agg', 'cairo', 

45 'pdf', 'pgf', 'ps', 'svg', 'template'] 

46all_backends = interactive_bk + non_interactive_bk 

47 

48 

49class ValidateInStrings: 

50 def __init__(self, key, valid, ignorecase=False): 

51 'valid is a list of legal strings' 

52 self.key = key 

53 self.ignorecase = ignorecase 

54 

55 def func(s): 

56 if ignorecase: 

57 return s.lower() 

58 else: 

59 return s 

60 self.valid = {func(k): k for k in valid} 

61 

62 def __call__(self, s): 

63 if self.ignorecase: 

64 s = s.lower() 

65 if s in self.valid: 

66 return self.valid[s] 

67 raise ValueError('Unrecognized %s string %r: valid strings are %s' 

68 % (self.key, s, list(self.valid.values()))) 

69 

70 

71def _listify_validator(scalar_validator, allow_stringlist=False, *, doc=None): 

72 def f(s): 

73 if isinstance(s, str): 

74 try: 

75 return [scalar_validator(v.strip()) for v in s.split(',') 

76 if v.strip()] 

77 except Exception: 

78 if allow_stringlist: 

79 # Sometimes, a list of colors might be a single string 

80 # of single-letter colornames. So give that a shot. 

81 return [scalar_validator(v.strip()) 

82 for v in s if v.strip()] 

83 else: 

84 raise 

85 # We should allow any generic sequence type, including generators, 

86 # Numpy ndarrays, and pandas data structures. However, unordered 

87 # sequences, such as sets, should be allowed but discouraged unless the 

88 # user desires pseudorandom behavior. 

89 elif isinstance(s, Iterable) and not isinstance(s, Mapping): 

90 # The condition on this list comprehension will preserve the 

91 # behavior of filtering out any empty strings (behavior was 

92 # from the original validate_stringlist()), while allowing 

93 # any non-string/text scalar values such as numbers and arrays. 

94 return [scalar_validator(v) for v in s 

95 if not isinstance(v, str) or v] 

96 else: 

97 raise ValueError("{!r} must be of type: str or non-dictionary " 

98 "iterable".format(s)) 

99 try: 

100 f.__name__ = "{}list".format(scalar_validator.__name__) 

101 except AttributeError: # class instance. 

102 f.__name__ = "{}List".format(type(scalar_validator).__name__) 

103 f.__doc__ = doc if doc is not None else scalar_validator.__doc__ 

104 return f 

105 

106 

107def validate_any(s): 

108 return s 

109validate_anylist = _listify_validator(validate_any) 

110 

111 

112@cbook.deprecated("3.2", alternative="os.path.exists") 

113def validate_path_exists(s): 

114 """If s is a path, return s, else False""" 

115 if s is None: 

116 return None 

117 if os.path.exists(s): 

118 return s 

119 else: 

120 raise RuntimeError('"%s" should be a path but it does not exist' % s) 

121 

122 

123def validate_bool(b): 

124 """Convert b to a boolean or raise""" 

125 if isinstance(b, str): 

126 b = b.lower() 

127 if b in ('t', 'y', 'yes', 'on', 'true', '1', 1, True): 

128 return True 

129 elif b in ('f', 'n', 'no', 'off', 'false', '0', 0, False): 

130 return False 

131 else: 

132 raise ValueError('Could not convert "%s" to boolean' % b) 

133 

134 

135def validate_bool_maybe_none(b): 

136 """Convert b to a boolean or raise.""" 

137 if isinstance(b, str): 

138 b = b.lower() 

139 if b is None or b == 'none': 

140 return None 

141 if b in ('t', 'y', 'yes', 'on', 'true', '1', 1, True): 

142 return True 

143 elif b in ('f', 'n', 'no', 'off', 'false', '0', 0, False): 

144 return False 

145 else: 

146 raise ValueError('Could not convert "%s" to boolean' % b) 

147 

148 

149def _validate_tex_preamble(s): 

150 if s is None or s == 'None': 

151 return "" 

152 try: 

153 if isinstance(s, str): 

154 return s 

155 elif isinstance(s, Iterable): 

156 return '\n'.join(s) 

157 else: 

158 raise TypeError 

159 except TypeError: 

160 raise ValueError('Could not convert "%s" to string' % s) 

161 

162 

163def validate_axisbelow(s): 

164 try: 

165 return validate_bool(s) 

166 except ValueError: 

167 if isinstance(s, str): 

168 s = s.lower() 

169 if s.startswith('line'): 

170 return 'line' 

171 raise ValueError('%s cannot be interpreted as' 

172 ' True, False, or "line"' % s) 

173 

174 

175def validate_dpi(s): 

176 """Confirm s is string 'figure' or convert s to float or raise.""" 

177 if s == 'figure': 

178 return s 

179 try: 

180 return float(s) 

181 except ValueError: 

182 raise ValueError('"%s" is not string "figure" or' 

183 ' could not convert "%s" to float' % (s, s)) 

184 

185 

186def _make_type_validator(cls, *, allow_none=False): 

187 """ 

188 Return a validator that converts inputs to *cls* or raises (and possibly 

189 allows ``None`` as well). 

190 """ 

191 

192 def validator(s): 

193 if (allow_none and 

194 (s is None or isinstance(s, str) and s.lower() == "none")): 

195 return None 

196 try: 

197 return cls(s) 

198 except ValueError: 

199 raise ValueError(f'Could not convert {s!r} to {cls.__name__}') 

200 

201 return validator 

202 

203 

204validate_string = _make_type_validator(str) 

205validate_string_or_None = _make_type_validator(str, allow_none=True) 

206validate_stringlist = _listify_validator( 

207 validate_string, doc='return a list or strings') 

208validate_int = _make_type_validator(int) 

209validate_int_or_None = _make_type_validator(int, allow_none=True) 

210validate_float = _make_type_validator(float) 

211validate_float_or_None = _make_type_validator(float, allow_none=True) 

212validate_floatlist = _listify_validator( 

213 validate_float, doc='return a list of floats') 

214 

215 

216def validate_fonttype(s): 

217 """ 

218 Confirm that this is a Postscript or PDF font type that we know how to 

219 convert to. 

220 """ 

221 fonttypes = {'type3': 3, 

222 'truetype': 42} 

223 try: 

224 fonttype = validate_int(s) 

225 except ValueError: 

226 try: 

227 return fonttypes[s.lower()] 

228 except KeyError: 

229 raise ValueError( 

230 'Supported Postscript/PDF font types are %s' % list(fonttypes)) 

231 else: 

232 if fonttype not in fonttypes.values(): 

233 raise ValueError( 

234 'Supported Postscript/PDF font types are %s' % 

235 list(fonttypes.values())) 

236 return fonttype 

237 

238 

239_validate_standard_backends = ValidateInStrings( 

240 'backend', all_backends, ignorecase=True) 

241_auto_backend_sentinel = object() 

242 

243 

244def validate_backend(s): 

245 backend = ( 

246 s if s is _auto_backend_sentinel or s.startswith("module://") 

247 else _validate_standard_backends(s)) 

248 return backend 

249 

250 

251@cbook.deprecated("3.1") 

252def validate_qt4(s): 

253 if s is None: 

254 return None 

255 return ValidateInStrings("backend.qt4", ['PyQt4', 'PySide', 'PyQt4v2'])(s) 

256 

257 

258@cbook.deprecated("3.1") 

259def validate_qt5(s): 

260 if s is None: 

261 return None 

262 return ValidateInStrings("backend.qt5", ['PyQt5', 'PySide2'])(s) 

263 

264 

265validate_toolbar = ValidateInStrings( 

266 'toolbar', ['None', 'toolbar2', 'toolmanager'], ignorecase=True) 

267 

268 

269def _make_nseq_validator(cls, n=None, allow_none=False): 

270 

271 def validator(s): 

272 """Convert *n* objects using ``cls``, or raise.""" 

273 if isinstance(s, str): 

274 s = [x.strip() for x in s.split(',')] 

275 if n is not None and len(s) != n: 

276 raise ValueError( 

277 f'Expected exactly {n} comma-separated values, ' 

278 f'but got {len(s)} comma-separated values: {s}') 

279 else: 

280 if n is not None and len(s) != n: 

281 raise ValueError( 

282 f'Expected exactly {n} values, ' 

283 f'but got {len(s)} values: {s}') 

284 try: 

285 return [cls(val) if not allow_none or val is not None else val 

286 for val in s] 

287 except ValueError: 

288 raise ValueError( 

289 f'Could not convert all entries to {cls.__name__}s') 

290 

291 return validator 

292 

293 

294validate_nseq_float = partial(_make_nseq_validator, float) 

295validate_nseq_int = partial(_make_nseq_validator, int) 

296 

297 

298def validate_color_or_inherit(s): 

299 """Return a valid color arg.""" 

300 if s == 'inherit': 

301 return s 

302 return validate_color(s) 

303 

304 

305def validate_color_or_auto(s): 

306 if s == 'auto': 

307 return s 

308 return validate_color(s) 

309 

310 

311def validate_color_for_prop_cycle(s): 

312 # Special-case the N-th color cycle syntax, this obviously can not 

313 # go in the color cycle. 

314 if isinstance(s, bytes): 

315 match = re.match(b'^C[0-9]$', s) 

316 if match is not None: 

317 raise ValueError('Can not put cycle reference ({cn!r}) in ' 

318 'prop_cycler'.format(cn=s)) 

319 elif isinstance(s, str): 

320 match = re.match('^C[0-9]$', s) 

321 if match is not None: 

322 raise ValueError('Can not put cycle reference ({cn!r}) in ' 

323 'prop_cycler'.format(cn=s)) 

324 return validate_color(s) 

325 

326 

327def validate_color(s): 

328 """Return a valid color arg.""" 

329 try: 

330 if s.lower() == 'none': 

331 return 'none' 

332 except AttributeError: 

333 pass 

334 

335 if isinstance(s, str): 

336 if len(s) == 6 or len(s) == 8: 

337 stmp = '#' + s 

338 if is_color_like(stmp): 

339 return stmp 

340 

341 if is_color_like(s): 

342 return s 

343 

344 # If it is still valid, it must be a tuple. 

345 colorarg = s 

346 msg = '' 

347 if s.find(',') >= 0: 

348 # get rid of grouping symbols 

349 stmp = ''.join([c for c in s if c.isdigit() or c == '.' or c == ',']) 

350 vals = stmp.split(',') 

351 if len(vals) not in [3, 4]: 

352 msg = '\nColor tuples must be of length 3 or 4' 

353 else: 

354 try: 

355 colorarg = [float(val) for val in vals] 

356 except ValueError: 

357 msg = '\nCould not convert all entries to floats' 

358 

359 if not msg and is_color_like(colorarg): 

360 return colorarg 

361 

362 raise ValueError('%s does not look like a color arg%s' % (s, msg)) 

363 

364 

365validate_colorlist = _listify_validator( 

366 validate_color, allow_stringlist=True, doc='return a list of colorspecs') 

367validate_orientation = ValidateInStrings( 

368 'orientation', ['landscape', 'portrait']) 

369 

370 

371def validate_aspect(s): 

372 if s in ('auto', 'equal'): 

373 return s 

374 try: 

375 return float(s) 

376 except ValueError: 

377 raise ValueError('not a valid aspect specification') 

378 

379 

380def validate_fontsize_None(s): 

381 if s is None or s == 'None': 

382 return None 

383 else: 

384 return validate_fontsize(s) 

385 

386 

387def validate_fontsize(s): 

388 fontsizes = ['xx-small', 'x-small', 'small', 'medium', 'large', 

389 'x-large', 'xx-large', 'smaller', 'larger'] 

390 if isinstance(s, str): 

391 s = s.lower() 

392 if s in fontsizes: 

393 return s 

394 try: 

395 return float(s) 

396 except ValueError: 

397 raise ValueError("%s is not a valid font size. Valid font sizes " 

398 "are %s." % (s, ", ".join(fontsizes))) 

399 

400 

401validate_fontsizelist = _listify_validator(validate_fontsize) 

402 

403 

404def validate_fontweight(s): 

405 weights = [ 

406 'ultralight', 'light', 'normal', 'regular', 'book', 'medium', 'roman', 

407 'semibold', 'demibold', 'demi', 'bold', 'heavy', 'extra bold', 'black'] 

408 # Note: Historically, weights have been case-sensitive in Matplotlib 

409 if s in weights: 

410 return s 

411 try: 

412 return int(s) 

413 except (ValueError, TypeError): 

414 raise ValueError(f'{s} is not a valid font weight.') 

415 

416 

417def validate_font_properties(s): 

418 parse_fontconfig_pattern(s) 

419 return s 

420 

421 

422validate_fontset = ValidateInStrings( 

423 'fontset', 

424 ['dejavusans', 'dejavuserif', 'cm', 'stix', 'stixsans', 'custom']) 

425 

426 

427def validate_mathtext_default(s): 

428 if s == "circled": 

429 cbook.warn_deprecated( 

430 "3.1", message="Support for setting the mathtext.default rcParam " 

431 "to 'circled' is deprecated since %(since)s and will be removed " 

432 "%(removal)s.") 

433 return ValidateInStrings( 

434 'default', 

435 "rm cal it tt sf bf default bb frak circled scr regular".split())(s) 

436 

437 

438_validate_alignment = ValidateInStrings( 

439 'alignment', 

440 ['center', 'top', 'bottom', 'baseline', 

441 'center_baseline']) 

442 

443 

444_validate_verbose = ValidateInStrings( 

445 'verbose', 

446 ['silent', 'helpful', 'debug', 'debug-annoying']) 

447 

448 

449@cbook.deprecated("3.1") 

450def validate_verbose(s): 

451 return _validate_verbose(s) 

452 

453 

454def validate_whiskers(s): 

455 if s == 'range': 

456 cbook.warn_deprecated( 

457 "3.2", message="Support for setting the boxplot.whiskers rcParam " 

458 "to 'range' is deprecated since %(since)s and will be removed " 

459 "%(removal)s; set it to 0, 100 instead.") 

460 return 'range' 

461 else: 

462 try: 

463 v = validate_nseq_float(2)(s) 

464 return v 

465 except (TypeError, ValueError): 

466 try: 

467 v = float(s) 

468 return v 

469 except ValueError: 

470 raise ValueError("Not a valid whisker value ['range', float, " 

471 "(float, float)]") 

472 

473 

474@cbook.deprecated("3.2") 

475def update_savefig_format(value): 

476 # The old savefig.extension could also have a value of "auto", but 

477 # the new savefig.format does not. We need to fix this here. 

478 value = validate_string(value) 

479 if value == 'auto': 

480 cbook.warn_deprecated( 

481 "3.2", message="Support for setting the 'savefig.format' rcParam " 

482 "to 'auto' is deprecated since %(since)s and will be removed " 

483 "%(removal)s; set it to 'png' instead.") 

484 value = 'png' 

485 return value 

486 

487 

488# Replace by validate_string once deprecation period passes. 

489def _update_savefig_format(value): 

490 # The old savefig.extension could also have a value of "auto", but 

491 # the new savefig.format does not. We need to fix this here. 

492 value = validate_string(value) 

493 if value == 'auto': 

494 cbook.warn_deprecated( 

495 "3.2", message="Support for setting the 'savefig.format' rcParam " 

496 "to 'auto' is deprecated since %(since)s and will be removed " 

497 "%(removal)s; set it to 'png' instead.") 

498 value = 'png' 

499 return value 

500 

501 

502validate_ps_papersize = ValidateInStrings( 

503 'ps_papersize', 

504 ['auto', 'letter', 'legal', 'ledger', 

505 'a0', 'a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8', 'a9', 'a10', 

506 'b0', 'b1', 'b2', 'b3', 'b4', 'b5', 'b6', 'b7', 'b8', 'b9', 'b10', 

507 ], ignorecase=True) 

508 

509 

510def validate_ps_distiller(s): 

511 if isinstance(s, str): 

512 s = s.lower() 

513 if s in ('none', None, 'false', False): 

514 return None 

515 elif s in ('ghostscript', 'xpdf'): 

516 try: 

517 mpl._get_executable_info("gs") 

518 except mpl.ExecutableNotFoundError: 

519 _log.warning("Setting rcParams['ps.usedistiller'] requires " 

520 "ghostscript.") 

521 return None 

522 if s == "xpdf": 

523 try: 

524 mpl._get_executable_info("pdftops") 

525 except mpl.ExecutableNotFoundError: 

526 _log.warning("Setting rcParams['ps.usedistiller'] to 'xpdf' " 

527 "requires xpdf.") 

528 return None 

529 return s 

530 else: 

531 raise ValueError('matplotlibrc ps.usedistiller must either be none, ' 

532 'ghostscript or xpdf') 

533 

534 

535validate_joinstyle = ValidateInStrings('joinstyle', 

536 ['miter', 'round', 'bevel'], 

537 ignorecase=True) 

538validate_joinstylelist = _listify_validator(validate_joinstyle) 

539 

540validate_capstyle = ValidateInStrings('capstyle', 

541 ['butt', 'round', 'projecting'], 

542 ignorecase=True) 

543validate_capstylelist = _listify_validator(validate_capstyle) 

544 

545validate_fillstyle = ValidateInStrings('markers.fillstyle', 

546 ['full', 'left', 'right', 'bottom', 

547 'top', 'none']) 

548validate_fillstylelist = _listify_validator(validate_fillstyle) 

549 

550 

551def validate_markevery(s): 

552 """ 

553 Validate the markevery property of a Line2D object. 

554 

555 Parameters 

556 ---------- 

557 s : None, int, float, slice, length-2 tuple of ints, 

558 length-2 tuple of floats, list of ints 

559 

560 Returns 

561 ------- 

562 s : None, int, float, slice, length-2 tuple of ints, 

563 length-2 tuple of floats, list of ints 

564 

565 """ 

566 # Validate s against type slice float int and None 

567 if isinstance(s, (slice, float, int, type(None))): 

568 return s 

569 # Validate s against type tuple 

570 if isinstance(s, tuple): 

571 if (len(s) == 2 

572 and (all(isinstance(e, int) for e in s) 

573 or all(isinstance(e, float) for e in s))): 

574 return s 

575 else: 

576 raise TypeError( 

577 "'markevery' tuple must be pair of ints or of floats") 

578 # Validate s against type list 

579 if isinstance(s, list): 

580 if all(isinstance(e, int) for e in s): 

581 return s 

582 else: 

583 raise TypeError( 

584 "'markevery' list must have all elements of type int") 

585 raise TypeError("'markevery' is of an invalid type") 

586 

587 

588validate_markeverylist = _listify_validator(validate_markevery) 

589 

590validate_legend_loc = ValidateInStrings( 

591 'legend_loc', 

592 ['best', 

593 'upper right', 

594 'upper left', 

595 'lower left', 

596 'lower right', 

597 'right', 

598 'center left', 

599 'center right', 

600 'lower center', 

601 'upper center', 

602 'center'], ignorecase=True) 

603 

604validate_svg_fonttype = ValidateInStrings('svg.fonttype', ['none', 'path']) 

605 

606 

607def validate_hinting(s): 

608 if s in (True, False): 

609 cbook.warn_deprecated( 

610 "3.2", message="Support for setting the text.hinting rcParam to " 

611 "True or False is deprecated since %(since)s and will be removed " 

612 "%(removal)s; set it to its synonyms 'auto' or 'none' instead.") 

613 return s 

614 if s.lower() in ('auto', 'native', 'either', 'none'): 

615 return s.lower() 

616 raise ValueError("hinting should be 'auto', 'native', 'either' or 'none'") 

617 

618 

619validate_pgf_texsystem = ValidateInStrings('pgf.texsystem', 

620 ['xelatex', 'lualatex', 'pdflatex']) 

621 

622validate_movie_writer = ValidateInStrings('animation.writer', 

623 ['ffmpeg', 'ffmpeg_file', 

624 'avconv', 'avconv_file', 

625 'imagemagick', 'imagemagick_file', 

626 'html']) 

627 

628validate_movie_frame_fmt = ValidateInStrings('animation.frame_format', 

629 ['png', 'jpeg', 'tiff', 'raw', 'rgba']) 

630 

631validate_axis_locator = ValidateInStrings('major', ['minor', 'both', 'major']) 

632 

633validate_movie_html_fmt = ValidateInStrings('animation.html', 

634 ['html5', 'jshtml', 'none']) 

635 

636 

637def validate_bbox(s): 

638 if isinstance(s, str): 

639 s = s.lower() 

640 if s == 'tight': 

641 return s 

642 if s == 'standard': 

643 return None 

644 raise ValueError("bbox should be 'tight' or 'standard'") 

645 elif s is not None: 

646 # Backwards compatibility. None is equivalent to 'standard'. 

647 raise ValueError("bbox should be 'tight' or 'standard'") 

648 return s 

649 

650 

651def validate_sketch(s): 

652 if isinstance(s, str): 

653 s = s.lower() 

654 if s == 'none' or s is None: 

655 return None 

656 if isinstance(s, str): 

657 result = tuple([float(v.strip()) for v in s.split(',')]) 

658 elif isinstance(s, (list, tuple)): 

659 result = tuple([float(v) for v in s]) 

660 if len(result) != 3: 

661 raise ValueError("path.sketch must be a tuple (scale, length, randomness)") 

662 return result 

663 

664 

665@cbook.deprecated("3.2") 

666class ValidateInterval: 

667 """ 

668 Value must be in interval 

669 """ 

670 def __init__(self, vmin, vmax, closedmin=True, closedmax=True): 

671 self.vmin = vmin 

672 self.vmax = vmax 

673 self.cmin = closedmin 

674 self.cmax = closedmax 

675 

676 def __call__(self, s): 

677 try: 

678 s = float(s) 

679 except ValueError: 

680 raise RuntimeError('Value must be a float; found "%s"' % s) 

681 

682 if self.cmin and s < self.vmin: 

683 raise RuntimeError('Value must be >= %f; found "%f"' % 

684 (self.vmin, s)) 

685 elif not self.cmin and s <= self.vmin: 

686 raise RuntimeError('Value must be > %f; found "%f"' % 

687 (self.vmin, s)) 

688 

689 if self.cmax and s > self.vmax: 

690 raise RuntimeError('Value must be <= %f; found "%f"' % 

691 (self.vmax, s)) 

692 elif not self.cmax and s >= self.vmax: 

693 raise RuntimeError('Value must be < %f; found "%f"' % 

694 (self.vmax, s)) 

695 return s 

696 

697 

698def _validate_greaterequal0_lessthan1(s): 

699 s = validate_float(s) 

700 if 0 <= s < 1: 

701 return s 

702 else: 

703 raise RuntimeError(f'Value must be >=0 and <1; got {s}') 

704 

705 

706def _validate_greaterequal0_lessequal1(s): 

707 s = validate_float(s) 

708 if 0 <= s <= 1: 

709 return s 

710 else: 

711 raise RuntimeError(f'Value must be >=0 and <=1; got {s}') 

712 

713 

714_range_validators = { # Slightly nicer (internal) API. 

715 "0 <= x < 1": _validate_greaterequal0_lessthan1, 

716 "0 <= x <= 1": _validate_greaterequal0_lessequal1, 

717} 

718 

719 

720validate_grid_axis = ValidateInStrings('axes.grid.axis', ['x', 'y', 'both']) 

721 

722 

723def validate_hatch(s): 

724 r""" 

725 Validate a hatch pattern. 

726 A hatch pattern string can have any sequence of the following 

727 characters: ``\ / | - + * . x o O``. 

728 """ 

729 if not isinstance(s, str): 

730 raise ValueError("Hatch pattern must be a string") 

731 cbook._check_isinstance(str, hatch_pattern=s) 

732 unknown = set(s) - {'\\', '/', '|', '-', '+', '*', '.', 'x', 'o', 'O'} 

733 if unknown: 

734 raise ValueError("Unknown hatch symbol(s): %s" % list(unknown)) 

735 return s 

736 

737 

738validate_hatchlist = _listify_validator(validate_hatch) 

739validate_dashlist = _listify_validator(validate_nseq_float(allow_none=True)) 

740 

741 

742_prop_validators = { 

743 'color': _listify_validator(validate_color_for_prop_cycle, 

744 allow_stringlist=True), 

745 'linewidth': validate_floatlist, 

746 'linestyle': validate_stringlist, 

747 'facecolor': validate_colorlist, 

748 'edgecolor': validate_colorlist, 

749 'joinstyle': validate_joinstylelist, 

750 'capstyle': validate_capstylelist, 

751 'fillstyle': validate_fillstylelist, 

752 'markerfacecolor': validate_colorlist, 

753 'markersize': validate_floatlist, 

754 'markeredgewidth': validate_floatlist, 

755 'markeredgecolor': validate_colorlist, 

756 'markevery': validate_markeverylist, 

757 'alpha': validate_floatlist, 

758 'marker': validate_stringlist, 

759 'hatch': validate_hatchlist, 

760 'dashes': validate_dashlist, 

761 } 

762_prop_aliases = { 

763 'c': 'color', 

764 'lw': 'linewidth', 

765 'ls': 'linestyle', 

766 'fc': 'facecolor', 

767 'ec': 'edgecolor', 

768 'mfc': 'markerfacecolor', 

769 'mec': 'markeredgecolor', 

770 'mew': 'markeredgewidth', 

771 'ms': 'markersize', 

772 } 

773 

774 

775def cycler(*args, **kwargs): 

776 """ 

777 Creates a `~cycler.Cycler` object much like :func:`cycler.cycler`, 

778 but includes input validation. 

779 

780 Call signatures:: 

781 

782 cycler(cycler) 

783 cycler(label=values[, label2=values2[, ...]]) 

784 cycler(label, values) 

785 

786 Form 1 copies a given `~cycler.Cycler` object. 

787 

788 Form 2 creates a `~cycler.Cycler` which cycles over one or more 

789 properties simultaneously. If multiple properties are given, their 

790 value lists must have the same length. 

791 

792 Form 3 creates a `~cycler.Cycler` for a single property. This form 

793 exists for compatibility with the original cycler. Its use is 

794 discouraged in favor of the kwarg form, i.e. ``cycler(label=values)``. 

795 

796 Parameters 

797 ---------- 

798 cycler : Cycler 

799 Copy constructor for Cycler. 

800 

801 label : str 

802 The property key. Must be a valid `.Artist` property. 

803 For example, 'color' or 'linestyle'. Aliases are allowed, 

804 such as 'c' for 'color' and 'lw' for 'linewidth'. 

805 

806 values : iterable 

807 Finite-length iterable of the property values. These values 

808 are validated and will raise a ValueError if invalid. 

809 

810 Returns 

811 ------- 

812 cycler : Cycler 

813 A new :class:`~cycler.Cycler` for the given properties. 

814 

815 Examples 

816 -------- 

817 Creating a cycler for a single property: 

818 

819 >>> c = cycler(color=['red', 'green', 'blue']) 

820 

821 Creating a cycler for simultaneously cycling over multiple properties 

822 (e.g. red circle, green plus, blue cross): 

823 

824 >>> c = cycler(color=['red', 'green', 'blue'], 

825 ... marker=['o', '+', 'x']) 

826 

827 """ 

828 if args and kwargs: 

829 raise TypeError("cycler() can only accept positional OR keyword " 

830 "arguments -- not both.") 

831 elif not args and not kwargs: 

832 raise TypeError("cycler() must have positional OR keyword arguments") 

833 

834 if len(args) == 1: 

835 if not isinstance(args[0], Cycler): 

836 raise TypeError("If only one positional argument given, it must " 

837 " be a Cycler instance.") 

838 return validate_cycler(args[0]) 

839 elif len(args) == 2: 

840 pairs = [(args[0], args[1])] 

841 elif len(args) > 2: 

842 raise TypeError("No more than 2 positional arguments allowed") 

843 else: 

844 pairs = kwargs.items() 

845 

846 validated = [] 

847 for prop, vals in pairs: 

848 norm_prop = _prop_aliases.get(prop, prop) 

849 validator = _prop_validators.get(norm_prop, None) 

850 if validator is None: 

851 raise TypeError("Unknown artist property: %s" % prop) 

852 vals = validator(vals) 

853 # We will normalize the property names as well to reduce 

854 # the amount of alias handling code elsewhere. 

855 validated.append((norm_prop, vals)) 

856 

857 return reduce(operator.add, (ccycler(k, v) for k, v in validated)) 

858 

859 

860def validate_cycler(s): 

861 """Return a Cycler object from a string repr or the object itself.""" 

862 if isinstance(s, str): 

863 try: 

864 # TODO: We might want to rethink this... 

865 # While I think I have it quite locked down, 

866 # it is execution of arbitrary code without 

867 # sanitation. 

868 # Combine this with the possibility that rcparams 

869 # might come from the internet (future plans), this 

870 # could be downright dangerous. 

871 # I locked it down by only having the 'cycler()' function 

872 # available. 

873 # UPDATE: Partly plugging a security hole. 

874 # I really should have read this: 

875 # http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html 

876 # We should replace this eval with a combo of PyParsing and 

877 # ast.literal_eval() 

878 if '.__' in s.replace(' ', ''): 

879 raise ValueError("'%s' seems to have dunder methods. Raising" 

880 " an exception for your safety") 

881 s = eval(s, {'cycler': cycler, '__builtins__': {}}) 

882 except BaseException as e: 

883 raise ValueError("'%s' is not a valid cycler construction: %s" % 

884 (s, e)) 

885 # Should make sure what comes from the above eval() 

886 # is a Cycler object. 

887 if isinstance(s, Cycler): 

888 cycler_inst = s 

889 else: 

890 raise ValueError("object was not a string or Cycler instance: %s" % s) 

891 

892 unknowns = cycler_inst.keys - (set(_prop_validators) | set(_prop_aliases)) 

893 if unknowns: 

894 raise ValueError("Unknown artist properties: %s" % unknowns) 

895 

896 # Not a full validation, but it'll at least normalize property names 

897 # A fuller validation would require v0.10 of cycler. 

898 checker = set() 

899 for prop in cycler_inst.keys: 

900 norm_prop = _prop_aliases.get(prop, prop) 

901 if norm_prop != prop and norm_prop in cycler_inst.keys: 

902 raise ValueError("Cannot specify both '{0}' and alias '{1}'" 

903 " in the same prop_cycle".format(norm_prop, prop)) 

904 if norm_prop in checker: 

905 raise ValueError("Another property was already aliased to '{0}'." 

906 " Collision normalizing '{1}'.".format(norm_prop, 

907 prop)) 

908 checker.update([norm_prop]) 

909 

910 # This is just an extra-careful check, just in case there is some 

911 # edge-case I haven't thought of. 

912 assert len(checker) == len(cycler_inst.keys) 

913 

914 # Now, it should be safe to mutate this cycler 

915 for prop in cycler_inst.keys: 

916 norm_prop = _prop_aliases.get(prop, prop) 

917 cycler_inst.change_key(prop, norm_prop) 

918 

919 for key, vals in cycler_inst.by_key().items(): 

920 _prop_validators[key](vals) 

921 

922 return cycler_inst 

923 

924 

925def validate_hist_bins(s): 

926 valid_strs = ["auto", "sturges", "fd", "doane", "scott", "rice", "sqrt"] 

927 if isinstance(s, str) and s in valid_strs: 

928 return s 

929 try: 

930 return int(s) 

931 except (TypeError, ValueError): 

932 pass 

933 try: 

934 return validate_floatlist(s) 

935 except ValueError: 

936 pass 

937 raise ValueError("'hist.bins' must be one of {}, an int or" 

938 " a sequence of floats".format(valid_strs)) 

939 

940 

941@cbook.deprecated("3.2") 

942def validate_animation_writer_path(p): 

943 # Make sure it's a string and then figure out if the animations 

944 # are already loaded and reset the writers (which will validate 

945 # the path on next call) 

946 cbook._check_isinstance(str, path=p) 

947 from sys import modules 

948 # set dirty, so that the next call to the registry will re-evaluate 

949 # the state. 

950 # only set dirty if already loaded. If not loaded, the load will 

951 # trigger the checks. 

952 if "matplotlib.animation" in modules: 

953 modules["matplotlib.animation"].writers.set_dirty() 

954 return p 

955 

956 

957def validate_webagg_address(s): 

958 if s is not None: 

959 import socket 

960 try: 

961 socket.inet_aton(s) 

962 except socket.error: 

963 raise ValueError("'webagg.address' is not a valid IP address") 

964 return s 

965 raise ValueError("'webagg.address' is not a valid IP address") 

966 

967 

968# A validator dedicated to the named line styles, based on the items in 

969# ls_mapper, and a list of possible strings read from Line2D.set_linestyle 

970_validate_named_linestyle = ValidateInStrings( 

971 'linestyle', 

972 [*ls_mapper.keys(), *ls_mapper.values(), 'None', 'none', ' ', ''], 

973 ignorecase=True) 

974 

975 

976def _validate_linestyle(ls): 

977 """ 

978 A validator for all possible line styles, the named ones *and* 

979 the on-off ink sequences. 

980 """ 

981 # Look first for a valid named line style, like '--' or 'solid' Also 

982 # includes bytes(-arrays) here (they all fail _validate_named_linestyle); 

983 # otherwise, if *ls* is of even-length, it will be passed to the instance 

984 # of validate_nseq_float, which will return an absurd on-off ink 

985 # sequence... 

986 if isinstance(ls, (str, bytes, bytearray)): 

987 return _validate_named_linestyle(ls) 

988 

989 # Look for an on-off ink sequence (in points) *of even length*. 

990 # Offset is set to None. 

991 try: 

992 if len(ls) % 2 != 0: 

993 raise ValueError("the linestyle sequence {!r} is not of even " 

994 "length.".format(ls)) 

995 

996 return (None, validate_nseq_float()(ls)) 

997 

998 except (ValueError, TypeError): 

999 # TypeError can be raised inside the instance of validate_nseq_float, 

1000 # by wrong types passed to float(), like NoneType. 

1001 raise ValueError("linestyle {!r} is not a valid on-off ink " 

1002 "sequence.".format(ls)) 

1003 

1004 

1005validate_axes_titlelocation = ValidateInStrings('axes.titlelocation', ['left', 'center', 'right']) 

1006 

1007# a map from key -> value, converter 

1008defaultParams = { 

1009 'backend': [_auto_backend_sentinel, validate_backend], 

1010 'backend_fallback': [True, validate_bool], 

1011 'webagg.port': [8988, validate_int], 

1012 'webagg.address': ['127.0.0.1', validate_webagg_address], 

1013 'webagg.open_in_browser': [True, validate_bool], 

1014 'webagg.port_retries': [50, validate_int], 

1015 'toolbar': ['toolbar2', validate_toolbar], 

1016 'datapath': [None, validate_any], # see _get_data_path_cached 

1017 'interactive': [False, validate_bool], 

1018 'timezone': ['UTC', validate_string], 

1019 

1020 # the verbosity setting 

1021 'verbose.level': ['silent', _validate_verbose], 

1022 'verbose.fileo': ['sys.stdout', validate_string], 

1023 

1024 # line props 

1025 'lines.linewidth': [1.5, validate_float], # line width in points 

1026 'lines.linestyle': ['-', _validate_linestyle], # solid line 

1027 'lines.color': ['C0', validate_color], # first color in color cycle 

1028 'lines.marker': ['None', validate_string], # marker name 

1029 'lines.markerfacecolor': ['auto', validate_color_or_auto], # default color 

1030 'lines.markeredgecolor': ['auto', validate_color_or_auto], # default color 

1031 'lines.markeredgewidth': [1.0, validate_float], 

1032 'lines.markersize': [6, validate_float], # markersize, in points 

1033 'lines.antialiased': [True, validate_bool], # antialiased (no jaggies) 

1034 'lines.dash_joinstyle': ['round', validate_joinstyle], 

1035 'lines.solid_joinstyle': ['round', validate_joinstyle], 

1036 'lines.dash_capstyle': ['butt', validate_capstyle], 

1037 'lines.solid_capstyle': ['projecting', validate_capstyle], 

1038 'lines.dashed_pattern': [[3.7, 1.6], validate_nseq_float(allow_none=True)], 

1039 'lines.dashdot_pattern': [[6.4, 1.6, 1, 1.6], 

1040 validate_nseq_float(allow_none=True)], 

1041 'lines.dotted_pattern': [[1, 1.65], validate_nseq_float(allow_none=True)], 

1042 'lines.scale_dashes': [True, validate_bool], 

1043 

1044 # marker props 

1045 'markers.fillstyle': ['full', validate_fillstyle], 

1046 

1047 ## patch props 

1048 'patch.linewidth': [1.0, validate_float], # line width in points 

1049 'patch.edgecolor': ['black', validate_color], 

1050 'patch.force_edgecolor': [False, validate_bool], 

1051 'patch.facecolor': ['C0', validate_color], # first color in cycle 

1052 'patch.antialiased': [True, validate_bool], # antialiased (no jaggies) 

1053 

1054 ## hatch props 

1055 'hatch.color': ['black', validate_color], 

1056 'hatch.linewidth': [1.0, validate_float], 

1057 

1058 ## Histogram properties 

1059 'hist.bins': [10, validate_hist_bins], 

1060 

1061 ## Boxplot properties 

1062 'boxplot.notch': [False, validate_bool], 

1063 'boxplot.vertical': [True, validate_bool], 

1064 'boxplot.whiskers': [1.5, validate_whiskers], 

1065 'boxplot.bootstrap': [None, validate_int_or_None], 

1066 'boxplot.patchartist': [False, validate_bool], 

1067 'boxplot.showmeans': [False, validate_bool], 

1068 'boxplot.showcaps': [True, validate_bool], 

1069 'boxplot.showbox': [True, validate_bool], 

1070 'boxplot.showfliers': [True, validate_bool], 

1071 'boxplot.meanline': [False, validate_bool], 

1072 

1073 'boxplot.flierprops.color': ['black', validate_color], 

1074 'boxplot.flierprops.marker': ['o', validate_string], 

1075 'boxplot.flierprops.markerfacecolor': ['none', validate_color_or_auto], 

1076 'boxplot.flierprops.markeredgecolor': ['black', validate_color], 

1077 'boxplot.flierprops.markeredgewidth': [1.0, validate_float], 

1078 'boxplot.flierprops.markersize': [6, validate_float], 

1079 'boxplot.flierprops.linestyle': ['none', _validate_linestyle], 

1080 'boxplot.flierprops.linewidth': [1.0, validate_float], 

1081 

1082 'boxplot.boxprops.color': ['black', validate_color], 

1083 'boxplot.boxprops.linewidth': [1.0, validate_float], 

1084 'boxplot.boxprops.linestyle': ['-', _validate_linestyle], 

1085 

1086 'boxplot.whiskerprops.color': ['black', validate_color], 

1087 'boxplot.whiskerprops.linewidth': [1.0, validate_float], 

1088 'boxplot.whiskerprops.linestyle': ['-', _validate_linestyle], 

1089 

1090 'boxplot.capprops.color': ['black', validate_color], 

1091 'boxplot.capprops.linewidth': [1.0, validate_float], 

1092 'boxplot.capprops.linestyle': ['-', _validate_linestyle], 

1093 

1094 'boxplot.medianprops.color': ['C1', validate_color], 

1095 'boxplot.medianprops.linewidth': [1.0, validate_float], 

1096 'boxplot.medianprops.linestyle': ['-', _validate_linestyle], 

1097 

1098 'boxplot.meanprops.color': ['C2', validate_color], 

1099 'boxplot.meanprops.marker': ['^', validate_string], 

1100 'boxplot.meanprops.markerfacecolor': ['C2', validate_color], 

1101 'boxplot.meanprops.markeredgecolor': ['C2', validate_color], 

1102 'boxplot.meanprops.markersize': [6, validate_float], 

1103 'boxplot.meanprops.linestyle': ['--', _validate_linestyle], 

1104 'boxplot.meanprops.linewidth': [1.0, validate_float], 

1105 

1106 ## font props 

1107 'font.family': [['sans-serif'], validate_stringlist], # used by text object 

1108 'font.style': ['normal', validate_string], 

1109 'font.variant': ['normal', validate_string], 

1110 'font.stretch': ['normal', validate_string], 

1111 'font.weight': ['normal', validate_fontweight], 

1112 'font.size': [10, validate_float], # Base font size in points 

1113 'font.serif': [['DejaVu Serif', 'Bitstream Vera Serif', 

1114 'Computer Modern Roman', 

1115 'New Century Schoolbook', 'Century Schoolbook L', 

1116 'Utopia', 'ITC Bookman', 'Bookman', 

1117 'Nimbus Roman No9 L', 'Times New Roman', 

1118 'Times', 'Palatino', 'Charter', 'serif'], 

1119 validate_stringlist], 

1120 'font.sans-serif': [['DejaVu Sans', 'Bitstream Vera Sans', 

1121 'Computer Modern Sans Serif', 

1122 'Lucida Grande', 'Verdana', 'Geneva', 'Lucid', 

1123 'Arial', 'Helvetica', 'Avant Garde', 'sans-serif'], 

1124 validate_stringlist], 

1125 'font.cursive': [['Apple Chancery', 'Textile', 'Zapf Chancery', 

1126 'Sand', 'Script MT', 'Felipa', 'cursive'], 

1127 validate_stringlist], 

1128 'font.fantasy': [['Comic Neue', 'Comic Sans MS', 'Chicago', 'Charcoal', 

1129 'Impact', 'Western', 'Humor Sans', 'xkcd', 'fantasy'], 

1130 validate_stringlist], 

1131 'font.monospace': [['DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 

1132 'Computer Modern Typewriter', 

1133 'Andale Mono', 'Nimbus Mono L', 'Courier New', 

1134 'Courier', 'Fixed', 'Terminal', 'monospace'], 

1135 validate_stringlist], 

1136 

1137 # text props 

1138 'text.color': ['black', validate_color], 

1139 'text.usetex': [False, validate_bool], 

1140 'text.latex.unicode': [True, validate_bool], 

1141 'text.latex.preamble': ['', _validate_tex_preamble], 

1142 'text.latex.preview': [False, validate_bool], 

1143 'text.hinting': ['auto', validate_hinting], 

1144 'text.hinting_factor': [8, validate_int], 

1145 'text.kerning_factor': [0, validate_int], 

1146 'text.antialiased': [True, validate_bool], 

1147 

1148 'mathtext.cal': ['cursive', validate_font_properties], 

1149 'mathtext.rm': ['sans', validate_font_properties], 

1150 'mathtext.tt': ['monospace', validate_font_properties], 

1151 'mathtext.it': ['sans:italic', validate_font_properties], 

1152 'mathtext.bf': ['sans:bold', validate_font_properties], 

1153 'mathtext.sf': ['sans', validate_font_properties], 

1154 'mathtext.fontset': ['dejavusans', validate_fontset], 

1155 'mathtext.default': ['it', validate_mathtext_default], 

1156 'mathtext.fallback_to_cm': [True, validate_bool], 

1157 

1158 'image.aspect': ['equal', validate_aspect], # equal, auto, a number 

1159 'image.interpolation': ['antialiased', validate_string], 

1160 'image.cmap': ['viridis', validate_string], # gray, jet, etc. 

1161 'image.lut': [256, validate_int], # lookup table 

1162 'image.origin': ['upper', 

1163 ValidateInStrings('image.origin', ['upper', 'lower'])], 

1164 'image.resample': [True, validate_bool], 

1165 # Specify whether vector graphics backends will combine all images on a 

1166 # set of axes into a single composite image 

1167 'image.composite_image': [True, validate_bool], 

1168 

1169 # contour props 

1170 'contour.negative_linestyle': ['dashed', _validate_linestyle], 

1171 'contour.corner_mask': [True, validate_bool], 

1172 

1173 # errorbar props 

1174 'errorbar.capsize': [0, validate_float], 

1175 

1176 # axes props 

1177 'axes.axisbelow': ['line', validate_axisbelow], 

1178 'axes.facecolor': ['white', validate_color], # background color 

1179 'axes.edgecolor': ['black', validate_color], # edge color 

1180 'axes.linewidth': [0.8, validate_float], # edge linewidth 

1181 

1182 'axes.spines.left': [True, validate_bool], # Set visibility of axes 

1183 'axes.spines.right': [True, validate_bool], # 'spines', the lines 

1184 'axes.spines.bottom': [True, validate_bool], # around the chart 

1185 'axes.spines.top': [True, validate_bool], # denoting data boundary 

1186 

1187 'axes.titlesize': ['large', validate_fontsize], # fontsize of the 

1188 # axes title 

1189 'axes.titlelocation': ['center', validate_axes_titlelocation], # alignment of axes title 

1190 'axes.titleweight': ['normal', validate_fontweight], # font weight of axes title 

1191 'axes.titlecolor': ['auto', validate_color_or_auto], # font color of axes title 

1192 'axes.titlepad': [6.0, validate_float], # pad from axes top to title in points 

1193 'axes.grid': [False, validate_bool], # display grid or not 

1194 'axes.grid.which': ['major', validate_axis_locator], # set whether the gid are by 

1195 # default draw on 'major' 

1196 # 'minor' or 'both' kind of 

1197 # axis locator 

1198 'axes.grid.axis': ['both', validate_grid_axis], # grid type: 

1199 # 'x', 'y', or 'both' 

1200 'axes.labelsize': ['medium', validate_fontsize], # fontsize of the 

1201 # x any y labels 

1202 'axes.labelpad': [4.0, validate_float], # space between label and axis 

1203 'axes.labelweight': ['normal', validate_fontweight], # fontsize of the x any y labels 

1204 'axes.labelcolor': ['black', validate_color], # color of axis label 

1205 'axes.formatter.limits': [[-5, 6], validate_nseq_int(2)], 

1206 # use scientific notation if log10 

1207 # of the axis range is smaller than the 

1208 # first or larger than the second 

1209 'axes.formatter.use_locale': [False, validate_bool], 

1210 # Use the current locale to format ticks 

1211 'axes.formatter.use_mathtext': [False, validate_bool], 

1212 'axes.formatter.min_exponent': [0, validate_int], # minimum exponent to format in scientific notation 

1213 'axes.formatter.useoffset': [True, validate_bool], 

1214 'axes.formatter.offset_threshold': [4, validate_int], 

1215 'axes.unicode_minus': [True, validate_bool], 

1216 # This entry can be either a cycler object or a 

1217 # string repr of a cycler-object, which gets eval()'ed 

1218 # to create the object. 

1219 'axes.prop_cycle': [ 

1220 ccycler('color', 

1221 ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', 

1222 '#9467bd', '#8c564b', '#e377c2', '#7f7f7f', 

1223 '#bcbd22', '#17becf']), 

1224 validate_cycler], 

1225 # If 'data', axes limits are set close to the data. 

1226 # If 'round_numbers' axes limits are set to the nearest round numbers. 

1227 'axes.autolimit_mode': [ 

1228 'data', 

1229 ValidateInStrings('autolimit_mode', ['data', 'round_numbers'])], 

1230 'axes.xmargin': [0.05, _range_validators["0 <= x <= 1"]], 

1231 'axes.ymargin': [0.05, _range_validators["0 <= x <= 1"]], 

1232 

1233 'polaraxes.grid': [True, validate_bool], # display polar grid or not 

1234 'axes3d.grid': [True, validate_bool], # display 3d grid 

1235 

1236 # scatter props 

1237 'scatter.marker': ['o', validate_string], 

1238 'scatter.edgecolors': ['face', validate_string], 

1239 

1240 # TODO validate that these are valid datetime format strings 

1241 'date.autoformatter.year': ['%Y', validate_string], 

1242 'date.autoformatter.month': ['%Y-%m', validate_string], 

1243 'date.autoformatter.day': ['%Y-%m-%d', validate_string], 

1244 'date.autoformatter.hour': ['%m-%d %H', validate_string], 

1245 'date.autoformatter.minute': ['%d %H:%M', validate_string], 

1246 'date.autoformatter.second': ['%H:%M:%S', validate_string], 

1247 'date.autoformatter.microsecond': ['%M:%S.%f', validate_string], 

1248 

1249 #legend properties 

1250 'legend.fancybox': [True, validate_bool], 

1251 'legend.loc': ['best', validate_legend_loc], 

1252 # the number of points in the legend line 

1253 'legend.numpoints': [1, validate_int], 

1254 # the number of points in the legend line for scatter 

1255 'legend.scatterpoints': [1, validate_int], 

1256 'legend.fontsize': ['medium', validate_fontsize], 

1257 'legend.title_fontsize': [None, validate_fontsize_None], 

1258 # the relative size of legend markers vs. original 

1259 'legend.markerscale': [1.0, validate_float], 

1260 'legend.shadow': [False, validate_bool], 

1261 # whether or not to draw a frame around legend 

1262 'legend.frameon': [True, validate_bool], 

1263 # alpha value of the legend frame 

1264 'legend.framealpha': [0.8, validate_float_or_None], 

1265 

1266 ## the following dimensions are in fraction of the font size 

1267 'legend.borderpad': [0.4, validate_float], # units are fontsize 

1268 # the vertical space between the legend entries 

1269 'legend.labelspacing': [0.5, validate_float], 

1270 # the length of the legend lines 

1271 'legend.handlelength': [2., validate_float], 

1272 # the length of the legend lines 

1273 'legend.handleheight': [0.7, validate_float], 

1274 # the space between the legend line and legend text 

1275 'legend.handletextpad': [.8, validate_float], 

1276 # the border between the axes and legend edge 

1277 'legend.borderaxespad': [0.5, validate_float], 

1278 # the border between the axes and legend edge 

1279 'legend.columnspacing': [2., validate_float], 

1280 'legend.facecolor': ['inherit', validate_color_or_inherit], 

1281 'legend.edgecolor': ['0.8', validate_color_or_inherit], 

1282 

1283 # tick properties 

1284 'xtick.top': [False, validate_bool], # draw ticks on the top side 

1285 'xtick.bottom': [True, validate_bool], # draw ticks on the bottom side 

1286 'xtick.labeltop': [False, validate_bool], # draw label on the top 

1287 'xtick.labelbottom': [True, validate_bool], # draw label on the bottom 

1288 'xtick.major.size': [3.5, validate_float], # major xtick size in points 

1289 'xtick.minor.size': [2, validate_float], # minor xtick size in points 

1290 'xtick.major.width': [0.8, validate_float], # major xtick width in points 

1291 'xtick.minor.width': [0.6, validate_float], # minor xtick width in points 

1292 'xtick.major.pad': [3.5, validate_float], # distance to label in points 

1293 'xtick.minor.pad': [3.4, validate_float], # distance to label in points 

1294 'xtick.color': ['black', validate_color], # color of the xtick labels 

1295 'xtick.minor.visible': [False, validate_bool], # visibility of the x axis minor ticks 

1296 'xtick.minor.top': [True, validate_bool], # draw x axis top minor ticks 

1297 'xtick.minor.bottom': [True, validate_bool], # draw x axis bottom minor ticks 

1298 'xtick.major.top': [True, validate_bool], # draw x axis top major ticks 

1299 'xtick.major.bottom': [True, validate_bool], # draw x axis bottom major ticks 

1300 

1301 # fontsize of the xtick labels 

1302 'xtick.labelsize': ['medium', validate_fontsize], 

1303 'xtick.direction': ['out', validate_string], # direction of xticks 

1304 'xtick.alignment': ["center", _validate_alignment], 

1305 

1306 'ytick.left': [True, validate_bool], # draw ticks on the left side 

1307 'ytick.right': [False, validate_bool], # draw ticks on the right side 

1308 'ytick.labelleft': [True, validate_bool], # draw tick labels on the left side 

1309 'ytick.labelright': [False, validate_bool], # draw tick labels on the right side 

1310 'ytick.major.size': [3.5, validate_float], # major ytick size in points 

1311 'ytick.minor.size': [2, validate_float], # minor ytick size in points 

1312 'ytick.major.width': [0.8, validate_float], # major ytick width in points 

1313 'ytick.minor.width': [0.6, validate_float], # minor ytick width in points 

1314 'ytick.major.pad': [3.5, validate_float], # distance to label in points 

1315 'ytick.minor.pad': [3.4, validate_float], # distance to label in points 

1316 'ytick.color': ['black', validate_color], # color of the ytick labels 

1317 'ytick.minor.visible': [False, validate_bool], # visibility of the y axis minor ticks 

1318 'ytick.minor.left': [True, validate_bool], # draw y axis left minor ticks 

1319 'ytick.minor.right': [True, validate_bool], # draw y axis right minor ticks 

1320 'ytick.major.left': [True, validate_bool], # draw y axis left major ticks 

1321 'ytick.major.right': [True, validate_bool], # draw y axis right major ticks 

1322 

1323 # fontsize of the ytick labels 

1324 'ytick.labelsize': ['medium', validate_fontsize], 

1325 'ytick.direction': ['out', validate_string], # direction of yticks 

1326 'ytick.alignment': ["center_baseline", _validate_alignment], 

1327 

1328 'grid.color': ['#b0b0b0', validate_color], # grid color 

1329 'grid.linestyle': ['-', _validate_linestyle], # solid 

1330 'grid.linewidth': [0.8, validate_float], # in points 

1331 'grid.alpha': [1.0, validate_float], 

1332 

1333 ## figure props 

1334 # figure title 

1335 'figure.titlesize': ['large', validate_fontsize], 

1336 'figure.titleweight': ['normal', validate_fontweight], 

1337 

1338 # figure size in inches: width by height 

1339 'figure.figsize': [[6.4, 4.8], validate_nseq_float(2)], 

1340 'figure.dpi': [100, validate_float], # DPI 

1341 'figure.facecolor': ['white', validate_color], 

1342 'figure.edgecolor': ['white', validate_color], 

1343 'figure.frameon': [True, validate_bool], 

1344 'figure.autolayout': [False, validate_bool], 

1345 'figure.max_open_warning': [20, validate_int], 

1346 

1347 'figure.subplot.left': [0.125, _range_validators["0 <= x <= 1"]], 

1348 'figure.subplot.right': [0.9, _range_validators["0 <= x <= 1"]], 

1349 'figure.subplot.bottom': [0.11, _range_validators["0 <= x <= 1"]], 

1350 'figure.subplot.top': [0.88, _range_validators["0 <= x <= 1"]], 

1351 'figure.subplot.wspace': [0.2, _range_validators["0 <= x < 1"]], 

1352 'figure.subplot.hspace': [0.2, _range_validators["0 <= x < 1"]], 

1353 

1354 # do constrained_layout. 

1355 'figure.constrained_layout.use': [False, validate_bool], 

1356 # wspace and hspace are fraction of adjacent subplots to use 

1357 # for space. Much smaller than above because we don't need 

1358 # room for the text. 

1359 'figure.constrained_layout.hspace': 

1360 [0.02, _range_validators["0 <= x < 1"]], 

1361 'figure.constrained_layout.wspace': 

1362 [0.02, _range_validators["0 <= x < 1"]], 

1363 # This is a buffer around the axes in inches. This is 3pts. 

1364 'figure.constrained_layout.h_pad': [0.04167, validate_float], 

1365 'figure.constrained_layout.w_pad': [0.04167, validate_float], 

1366 

1367 ## Saving figure's properties 

1368 'savefig.dpi': ['figure', validate_dpi], # DPI 

1369 'savefig.facecolor': ['white', validate_color], 

1370 'savefig.edgecolor': ['white', validate_color], 

1371 'savefig.frameon': [True, validate_bool], 

1372 'savefig.orientation': ['portrait', validate_orientation], 

1373 'savefig.jpeg_quality': [95, validate_int], 

1374 # value checked by backend at runtime 

1375 'savefig.format': ['png', _update_savefig_format], 

1376 # options are 'tight', or 'standard'. 'standard' validates to None. 

1377 'savefig.bbox': ['standard', validate_bbox], 

1378 'savefig.pad_inches': [0.1, validate_float], 

1379 # default directory in savefig dialog box 

1380 'savefig.directory': ['~', validate_string], 

1381 'savefig.transparent': [False, validate_bool], 

1382 

1383 # Maintain shell focus for TkAgg 

1384 'tk.window_focus': [False, validate_bool], 

1385 

1386 # Set the papersize/type 

1387 'ps.papersize': ['letter', validate_ps_papersize], 

1388 'ps.useafm': [False, validate_bool], 

1389 # use ghostscript or xpdf to distill ps output 

1390 'ps.usedistiller': [False, validate_ps_distiller], 

1391 'ps.distiller.res': [6000, validate_int], # dpi 

1392 'ps.fonttype': [3, validate_fonttype], # 3 (Type3) or 42 (Truetype) 

1393 # compression level from 0 to 9; 0 to disable 

1394 'pdf.compression': [6, validate_int], 

1395 # ignore any color-setting commands from the frontend 

1396 'pdf.inheritcolor': [False, validate_bool], 

1397 # use only the 14 PDF core fonts embedded in every PDF viewing application 

1398 'pdf.use14corefonts': [False, validate_bool], 

1399 'pdf.fonttype': [3, validate_fonttype], # 3 (Type3) or 42 (Truetype) 

1400 

1401 'pgf.debug': [False, validate_bool], # output debug information 

1402 # choose latex application for creating pdf files (xelatex/lualatex) 

1403 'pgf.texsystem': ['xelatex', validate_pgf_texsystem], 

1404 # use matplotlib rc settings for font configuration 

1405 'pgf.rcfonts': [True, validate_bool], 

1406 # provide a custom preamble for the latex process 

1407 'pgf.preamble': ['', _validate_tex_preamble], 

1408 

1409 # write raster image data directly into the svg file 

1410 'svg.image_inline': [True, validate_bool], 

1411 # True to save all characters as paths in the SVG 

1412 'svg.fonttype': ['path', validate_svg_fonttype], 

1413 'svg.hashsalt': [None, validate_string_or_None], 

1414 

1415 # set this when you want to generate hardcopy docstring 

1416 'docstring.hardcopy': [False, validate_bool], 

1417 

1418 'path.simplify': [True, validate_bool], 

1419 'path.simplify_threshold': [1 / 9, _range_validators["0 <= x <= 1"]], 

1420 'path.snap': [True, validate_bool], 

1421 'path.sketch': [None, validate_sketch], 

1422 'path.effects': [[], validate_any], 

1423 'agg.path.chunksize': [0, validate_int], # 0 to disable chunking; 

1424 

1425 # key-mappings (multi-character mappings should be a list/tuple) 

1426 'keymap.fullscreen': [['f', 'ctrl+f'], validate_stringlist], 

1427 'keymap.home': [['h', 'r', 'home'], validate_stringlist], 

1428 'keymap.back': [['left', 'c', 'backspace', 'MouseButton.BACK'], 

1429 validate_stringlist], 

1430 'keymap.forward': [['right', 'v', 'MouseButton.FORWARD'], 

1431 validate_stringlist], 

1432 'keymap.pan': [['p'], validate_stringlist], 

1433 'keymap.zoom': [['o'], validate_stringlist], 

1434 'keymap.save': [['s', 'ctrl+s'], validate_stringlist], 

1435 'keymap.quit': [['ctrl+w', 'cmd+w', 'q'], validate_stringlist], 

1436 'keymap.quit_all': [['W', 'cmd+W', 'Q'], validate_stringlist], 

1437 'keymap.grid': [['g'], validate_stringlist], 

1438 'keymap.grid_minor': [['G'], validate_stringlist], 

1439 'keymap.yscale': [['l'], validate_stringlist], 

1440 'keymap.xscale': [['k', 'L'], validate_stringlist], 

1441 'keymap.all_axes': [['a'], validate_stringlist], 

1442 'keymap.help': [['f1'], validate_stringlist], 

1443 'keymap.copy': [['ctrl+c', 'cmd+c'], validate_stringlist], 

1444 

1445 # Animation settings 

1446 'animation.html': ['none', validate_movie_html_fmt], 

1447 # Limit, in MB, of size of base64 encoded animation in HTML 

1448 # (i.e. IPython notebook) 

1449 'animation.embed_limit': [20, validate_float], 

1450 'animation.writer': ['ffmpeg', validate_movie_writer], 

1451 'animation.codec': ['h264', validate_string], 

1452 'animation.bitrate': [-1, validate_int], 

1453 # Controls image format when frames are written to disk 

1454 'animation.frame_format': ['png', validate_movie_frame_fmt], 

1455 # Additional arguments for HTML writer 

1456 'animation.html_args': [[], validate_stringlist], 

1457 # Path to ffmpeg binary. If just binary name, subprocess uses $PATH. 

1458 'animation.ffmpeg_path': ['ffmpeg', validate_string], 

1459 # Additional arguments for ffmpeg movie writer (using pipes) 

1460 'animation.ffmpeg_args': [[], validate_stringlist], 

1461 # Path to AVConv binary. If just binary name, subprocess uses $PATH. 

1462 'animation.avconv_path': ['avconv', validate_string], 

1463 # Additional arguments for avconv movie writer (using pipes) 

1464 'animation.avconv_args': [[], validate_stringlist], 

1465 # Path to convert binary. If just binary name, subprocess uses $PATH. 

1466 'animation.convert_path': ['convert', validate_string], 

1467 # Additional arguments for convert movie writer (using pipes) 

1468 'animation.convert_args': [[], validate_stringlist], 

1469 

1470 'mpl_toolkits.legacy_colorbar': [True, validate_bool], 

1471 

1472 # Classic (pre 2.0) compatibility mode 

1473 # This is used for things that are hard to make backward compatible 

1474 # with a sane rcParam alone. This does *not* turn on classic mode 

1475 # altogether. For that use `matplotlib.style.use('classic')`. 

1476 '_internal.classic_mode': [False, validate_bool] 

1477}