Skip to content

Commit 684480a

Browse files
committed
Use _write_defaults to generate user/docs proplotrc
1 parent 527901c commit 684480a

File tree

2 files changed

+91
-3
lines changed

2 files changed

+91
-3
lines changed

docs/conf.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@
1313

1414
import os
1515
import sys
16+
from proplot.rctools import _write_defaults
1617
from pygments.formatters import HtmlFormatter
1718
from pygments.styles import get_all_styles
1819

19-
# Sphinx-automodapi requires proplot on path
20+
# Add proplot to path for sphinx-automodapi
2021
sys.path.insert(0, os.path.abspath('..'))
2122

2223
# Add docs folder to PATH for local 'sphinxext' extensions
@@ -194,6 +195,9 @@
194195
with open(path, 'w') as f:
195196
f.write(HtmlFormatter(style=style).get_style_defs('.highlight'))
196197

198+
# Create sample .proplotrc file
199+
_write_defaults(os.path.join('_static', 'proplotrc'), comment=False)
200+
197201
# Role
198202
# default family is py, but can also set default role so don't need
199203
# :func:`name`, :module:`name`, etc.

proplot/rctools.py

Lines changed: 86 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import cycler
1313
import matplotlib.colors as mcolors
1414
import matplotlib.cm as mcm
15+
from numbers import Number
1516
from matplotlib import style, rcParams
1617
try:
1718
import IPython
@@ -276,8 +277,7 @@ def _tabulate(rcdict):
276277
""".strip())
277278

278279
# "Global" settings and the lower-level settings they change
279-
# NOTE: This whole section, declaring dictionaries and sets, takes 1ms
280-
RC_CHILDREN = {
280+
_rc_children = {
281281
'cmap': (
282282
'image.cmap',
283283
),
@@ -729,6 +729,85 @@ def _update_from_file(file):
729729
rcParams.update(rc)
730730

731731

732+
def _write_defaults(filename, comment=True, overwrite=False):
733+
"""
734+
Save a file to the specified path containing the default `rc` settings.
735+
736+
Parameters
737+
----------
738+
filename : str
739+
The path.
740+
comment : bool, optional
741+
Whether to "comment out" each setting.
742+
overwrite : bool, optional
743+
Whether to overwrite existing files.
744+
"""
745+
def _tabulate(rcdict):
746+
string = ''
747+
prefix = '# ' if comment else ''
748+
maxlen = max(map(len, rcdict))
749+
NoneType = type(None)
750+
for key, value in rcdict.items():
751+
if isinstance(value, cycler.Cycler): # special case!
752+
value = repr(value)
753+
elif isinstance(value, (str, Number, NoneType)):
754+
value = str(value)
755+
elif isinstance(value, (list, tuple)) and all(
756+
isinstance(val, (str, Number)) for val in value
757+
):
758+
value = ', '.join(str(val) for val in value)
759+
else:
760+
raise ValueError(
761+
f'Failed to write rc setting {key} = {value!r}. '
762+
'Must be string, number, or list or tuple thereof, '
763+
'or None or a cycler.'
764+
)
765+
space = ' ' * (maxlen - len(key) + 1)
766+
string += f'{prefix}{key}:{space}{value}\n'
767+
return string.strip()
768+
769+
# Fill empty defaultParamsLong values with rcDefaultParamsShort
770+
# They are only allowed to be None in the *default dictionaries* because
771+
# they are immediately overwritten. However if users try to set them as
772+
# None in a .proplotrc file, may trigger error down the line.
773+
rc_parents = {
774+
child: parent
775+
for parent, children in _rc_children.items()
776+
for child in children
777+
}
778+
defaultParamsLong_filled = defaultParamsLong.copy()
779+
for key, value in defaultParamsLong.items():
780+
if value is None:
781+
try:
782+
defaultParamsLong_filled[key] = rc_parents[key]
783+
except KeyError:
784+
raise RuntimeError(
785+
f'rcParamsLong param {key!r} has default value of None '
786+
'but has no rcParmsShort parent!'
787+
)
788+
789+
value = defaultParamsShort
790+
791+
with open(filename, 'w') as f:
792+
f.write(f"""
793+
#---------------------------------------------------------------------
794+
# Use this file to change the default proplot and matplotlib settings
795+
# The syntax is mostly the same as for matplotlibrc files
796+
# For descriptions of each setting see:
797+
# https://proplot.readthedocs.io/en/latest/rctools.html
798+
# https://matplotlib.org/3.1.1/tutorials/introductory/customizing.html
799+
#---------------------------------------------------------------------
800+
# ProPlot short name settings
801+
{_tabulate(defaultParamsShort)}
802+
803+
# ProPlot long name settings
804+
{_tabulate(defaultParamsLong_filled)}
805+
806+
# Matplotlib settings
807+
{_tabulate(defaultParams)}
808+
""".strip())
809+
810+
732811
class rc_configurator(object):
733812
"""
734813
Magical abstract class for managing matplotlib
@@ -1262,6 +1341,11 @@ def ipython_autosave(autosave=None):
12621341
pass
12631342

12641343

1344+
# Write defaults
1345+
_user_rc_file = os.path.join(os.path.expanduser('~'), '.proplotrc')
1346+
if not os.path.exists(_user_rc_file):
1347+
_write_defaults(_user_rc_file)
1348+
12651349
#: Instance of `rc_configurator`. This is used to change global settings.
12661350
#: See :ref:`Configuring proplot` for details.
12671351
rc = rc_configurator()

0 commit comments

Comments
 (0)