Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Add _val_or_rc-function #26168

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions lib/matplotlib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1294,6 +1294,13 @@ def is_interactive():
return rcParams['interactive']


def _val_or_rc(val, rc_name):
"""
If *val* is None, return ``mpl.rcParams[rc_name]``, otherwise return val.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
If *val* is None, return ``mpl.rcParams[rc_name]``, otherwise return val.
Return the value if present, otherwise lookup `rc_name` in the rcParams dictionary.

I'd suggest rewording this to be more human friendly since the code already explains what you had written.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using None and mpl.rcParams[rc_name] is good, because that's precise and comprehensible. Optional, slightly less algorithmic variant.

Suggested change
If *val* is None, return ``mpl.rcParams[rc_name]``, otherwise return val.
Pass *val* through unless it is None, in which case return ``mpl.rcParams[rc_name]``.

"""
return val if val is not None else rcParams[rc_name]


def _init_tests():
# The version of FreeType to install locally for running the
# tests. This must match the value in `setupext.py`
Expand Down
3 changes: 2 additions & 1 deletion lib/matplotlib/_mathtext.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,11 @@ def to_raster(self):
# old approach and keeps baseline images backcompat.
shifted = ship(self.box, (-xmin, -ymin))

antialiased = mpl.rcParams['text.antialiased']
for ox, oy, info in shifted.glyphs:
info.font.draw_glyph_to_bitmap(
image, ox, oy - info.metrics.iceberg, info.glyph,
antialiased=mpl.rcParams['text.antialiased'])
antialiased=antialiased)
for x1, y1, x2, y2 in shifted.rects:
height = max(int(y2 - y1) - 1, 0)
if height == 0:
Expand Down
17 changes: 5 additions & 12 deletions lib/matplotlib/animation.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,8 @@ class AbstractMovieWriter(abc.ABC):
def __init__(self, fps=5, metadata=None, codec=None, bitrate=None):
self.fps = fps
self.metadata = metadata if metadata is not None else {}
self.codec = (
mpl.rcParams['animation.codec'] if codec is None else codec)
self.bitrate = (
mpl.rcParams['animation.bitrate'] if bitrate is None else bitrate)
self.codec = mpl._val_or_rc(codec, 'animation.codec')
self.bitrate = mpl._val_or_rc(bitrate, 'animation.bitrate')

@abc.abstractmethod
def setup(self, fig, outfile, dpi=None):
Expand Down Expand Up @@ -733,10 +731,7 @@ def __init__(self, fps=30, codec=None, bitrate=None, extra_args=None,
default_mode=self.default_mode)

# Save embed limit, which is given in MB
if embed_limit is None:
self._bytes_limit = mpl.rcParams['animation.embed_limit']
else:
self._bytes_limit = embed_limit
self._bytes_limit = mpl._val_or_rc(embed_limit, 'animation.embed_limit')
# Convert from MB to bytes
self._bytes_limit *= 1024 * 1024

Expand Down Expand Up @@ -1028,8 +1023,7 @@ def func(current_frame: int, total_frames: int) -> Any
fps = 1000. / self._interval

# Re-use the savefig DPI for ours if none is given
if dpi is None:
dpi = mpl.rcParams['savefig.dpi']
dpi = mpl._val_or_rc(dpi, 'savefig.dpi')
if dpi == 'figure':
dpi = self._fig.dpi

Expand Down Expand Up @@ -1267,8 +1261,7 @@ def to_html5_video(self, embed_limit=None):
# Cache the rendering of the video as HTML
if not hasattr(self, '_base64_video'):
# Save embed limit, which is given in MB
if embed_limit is None:
embed_limit = mpl.rcParams['animation.embed_limit']
embed_limit = mpl._val_or_rc(embed_limit, 'animation.embed_limit')

# Convert from MB to bytes
embed_limit *= 1024 * 1024
Expand Down
9 changes: 3 additions & 6 deletions lib/matplotlib/axis.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,12 +139,9 @@ def __init__(
zorder = mlines.Line2D.zorder
self._zorder = zorder

if grid_color is None:
grid_color = mpl.rcParams["grid.color"]
if grid_linestyle is None:
grid_linestyle = mpl.rcParams["grid.linestyle"]
if grid_linewidth is None:
grid_linewidth = mpl.rcParams["grid.linewidth"]
grid_color = mpl._val_or_rc(grid_color, "grid.color")
grid_linestyle = mpl._val_or_rc(grid_linestyle, "grid.linestyle")
grid_linewidth = mpl._val_or_rc(grid_linewidth, "grid.linewidth")
if grid_alpha is None and not mcolors._has_alpha_channel(grid_color):
# alpha precedence: kwarg > color alpha > rcParams['grid.alpha']
# Note: only resolve to rcParams if the color does not have alpha
Expand Down
19 changes: 7 additions & 12 deletions lib/matplotlib/dates.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,10 +218,9 @@ def _get_tzinfo(tz=None):
Generate `~datetime.tzinfo` from a string or return `~datetime.tzinfo`.
If None, retrieve the preferred timezone from the rcParams dictionary.
"""
if tz is None:
tz = mpl.rcParams['timezone']
if tz == 'UTC':
return UTC
tz = mpl._val_or_rc(tz, 'timezone')
if tz == 'UTC':
return UTC
if isinstance(tz, str):
tzinfo = dateutil.tz.gettz(tz)
if tzinfo is None:
Expand Down Expand Up @@ -312,8 +311,7 @@ def get_epoch():
"""
global _epoch

if _epoch is None:
_epoch = mpl.rcParams['date.epoch']
_epoch = mpl._val_or_rc(_epoch, 'date.epoch')
return _epoch


Expand Down Expand Up @@ -641,8 +639,7 @@ def __init__(self, fmt, tz=None, *, usetex=None):
"""
self.tz = _get_tzinfo(tz)
self.fmt = fmt
self._usetex = (usetex if usetex is not None else
mpl.rcParams['text.usetex'])
self._usetex = mpl._val_or_rc(usetex, 'text.usetex')

def __call__(self, x, pos=0):
result = num2date(x, self.tz).strftime(self.fmt)
Expand Down Expand Up @@ -779,8 +776,7 @@ def __init__(self, locator, tz=None, formats=None, offset_formats=None,
'%Y-%b-%d %H:%M']
self.offset_string = ''
self.show_offset = show_offset
self._usetex = (usetex if usetex is not None else
mpl.rcParams['text.usetex'])
self._usetex = mpl._val_or_rc(usetex, 'text.usetex')

def __call__(self, x, pos=None):
formatter = DateFormatter(self.defaultfmt, self._tz,
Expand Down Expand Up @@ -957,8 +953,7 @@ def __init__(self, locator, tz=None, defaultfmt='%Y-%m-%d', *,
self.defaultfmt = defaultfmt
self._formatter = DateFormatter(self.defaultfmt, tz)
rcParams = mpl.rcParams
self._usetex = (usetex if usetex is not None else
mpl.rcParams['text.usetex'])
self._usetex = mpl._val_or_rc(usetex, 'text.usetex')
self.scaled = {
DAYS_PER_YEAR: rcParams['date.autoformatter.year'],
DAYS_PER_MONTH: rcParams['date.autoformatter.month'],
Expand Down
11 changes: 5 additions & 6 deletions lib/matplotlib/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -773,10 +773,8 @@ def set_interpolation(self, s):
'spline36', 'hanning', 'hamming', 'hermite', 'kaiser', 'quadric', 'catrom', \
'gaussian', 'bessel', 'mitchell', 'sinc', 'lanczos', 'none'} or None
"""
if s is None:
s = mpl.rcParams['image.interpolation']
s = s.lower()
_api.check_in_list(_interpd_, interpolation=s)
s = mpl._val_or_rc(s, 'image.interpolation').lower()
_api.check_in_list(interpolations_names, interpolation=s)
self._interpolation = s
self.stale = True

Expand Down Expand Up @@ -813,8 +811,7 @@ def set_resample(self, v):
v : bool or None
If None, use :rc:`image.resample`.
"""
if v is None:
v = mpl.rcParams['image.resample']
v = mpl._val_or_rc(v, 'image.resample')
self._resample = v
self.stale = True

Expand Down Expand Up @@ -1614,6 +1611,8 @@ def imsave(fname, arr, vmin=None, vmax=None, cmap=None, format=None,
# size when dividing and then multiplying by dpi.
if origin is None:
origin = mpl.rcParams["image.origin"]
else:
_api.check_in_list(('upper', 'lower'), origin=origin)
if origin == "lower":
arr = arr[::-1]
if (isinstance(arr, memoryview) and arr.format == "B"
Expand Down
49 changes: 18 additions & 31 deletions lib/matplotlib/legend.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,11 +427,7 @@ def __init__(
super().__init__()

if prop is None:
if fontsize is not None:
self.prop = FontProperties(size=fontsize)
else:
self.prop = FontProperties(
size=mpl.rcParams["legend.fontsize"])
self.prop = FontProperties(size=mpl._val_or_rc(fontsize, "legend.fontsize"))
else:
self.prop = FontProperties._from_any(prop)
if isinstance(prop, dict) and "size" not in prop:
Expand All @@ -447,20 +443,17 @@ def __init__(
#: instance.
self._custom_handler_map = handler_map

def val_or_rc(val, rc_name):
return val if val is not None else mpl.rcParams[rc_name]
Comment on lines -450 to -451
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you could possibly save a bunch of method gets below by setting this and reusing it?
val_or_rc = mpl._val_or_rc

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to warn on ineffective micro optimizations. Squeezing out nanoseconds does not make any measureable difference.

A function lookup cost 30ns (Python 3.11):

In [2]: %timeit mpl.rc_params_from_file
29.7 ns ± 0.544 ns per loop

If we want to improve performance (and there's a lot to gain) that would need to be guided by profiling to identify the real pain points. In other cases, code structure/readability should be the primary guideline. - Not shure what is better here, but I tend to not do the additional logic indirection for saving a method to a new variable just to save method lookups.


self.numpoints = val_or_rc(numpoints, 'legend.numpoints')
self.markerscale = val_or_rc(markerscale, 'legend.markerscale')
self.scatterpoints = val_or_rc(scatterpoints, 'legend.scatterpoints')
self.borderpad = val_or_rc(borderpad, 'legend.borderpad')
self.labelspacing = val_or_rc(labelspacing, 'legend.labelspacing')
self.handlelength = val_or_rc(handlelength, 'legend.handlelength')
self.handleheight = val_or_rc(handleheight, 'legend.handleheight')
self.handletextpad = val_or_rc(handletextpad, 'legend.handletextpad')
self.borderaxespad = val_or_rc(borderaxespad, 'legend.borderaxespad')
self.columnspacing = val_or_rc(columnspacing, 'legend.columnspacing')
self.shadow = val_or_rc(shadow, 'legend.shadow')
self.numpoints = mpl._val_or_rc(numpoints, 'legend.numpoints')
self.markerscale = mpl._val_or_rc(markerscale, 'legend.markerscale')
self.scatterpoints = mpl._val_or_rc(scatterpoints, 'legend.scatterpoints')
self.borderpad = mpl._val_or_rc(borderpad, 'legend.borderpad')
self.labelspacing = mpl._val_or_rc(labelspacing, 'legend.labelspacing')
self.handlelength = mpl._val_or_rc(handlelength, 'legend.handlelength')
self.handleheight = mpl._val_or_rc(handleheight, 'legend.handleheight')
self.handletextpad = mpl._val_or_rc(handletextpad, 'legend.handletextpad')
self.borderaxespad = mpl._val_or_rc(borderaxespad, 'legend.borderaxespad')
self.columnspacing = mpl._val_or_rc(columnspacing, 'legend.columnspacing')
self.shadow = mpl._val_or_rc(shadow, 'legend.shadow')
# trim handles and labels if illegal label...
_lab, _hand = [], []
for label, handle in zip(labels, handles):
Expand Down Expand Up @@ -533,18 +526,15 @@ def val_or_rc(val, rc_name):
# We use FancyBboxPatch to draw a legend frame. The location
# and size of the box will be updated during the drawing time.

if facecolor is None:
facecolor = mpl.rcParams["legend.facecolor"]
facecolor = mpl._val_or_rc(facecolor, "legend.facecolor")
if facecolor == 'inherit':
facecolor = mpl.rcParams["axes.facecolor"]

if edgecolor is None:
edgecolor = mpl.rcParams["legend.edgecolor"]
edgecolor = mpl._val_or_rc(edgecolor, "legend.edgecolor")
if edgecolor == 'inherit':
edgecolor = mpl.rcParams["axes.edgecolor"]

if fancybox is None:
fancybox = mpl.rcParams["legend.fancybox"]
fancybox = mpl._val_or_rc(fancybox, "legend.fancybox")

self.legendPatch = FancyBboxPatch(
xy=(0, 0), width=1, height=1,
Expand All @@ -559,8 +549,7 @@ def val_or_rc(val, rc_name):
else "square,pad=0"),
mutation_scale=self._fontsize,
snap=True,
visible=(frameon if frameon is not None
else mpl.rcParams["legend.frameon"])
visible=mpl._val_or_rc(frameon, "legend.frameon")
)
self._set_artist_props(self.legendPatch)

Expand Down Expand Up @@ -603,11 +592,9 @@ def val_or_rc(val, rc_name):
'markeredgecolor': ['get_markeredgecolor', 'get_edgecolor'],
'mec': ['get_markeredgecolor', 'get_edgecolor'],
}
labelcolor = mpl._val_or_rc(labelcolor, 'legend.labelcolor')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could nest another mpl._val_or_rc(..., 'text.color') here and add a short comment about falling back to text.color if legend.labelcolor is not present.

if labelcolor is None:
if mpl.rcParams['legend.labelcolor'] is not None:
labelcolor = mpl.rcParams['legend.labelcolor']
else:
labelcolor = mpl.rcParams['text.color']
labelcolor = mpl.rcParams['text.color']
if isinstance(labelcolor, str) and labelcolor in color_getters:
getter_names = color_getters[labelcolor]
for handle, text in zip(self.legend_handles, self.texts):
Expand Down
6 changes: 2 additions & 4 deletions lib/matplotlib/text.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,12 +173,10 @@ def _reset_visual_defaults(
antialiased=None
):
self.set_text(text)
self.set_color(
color if color is not None else mpl.rcParams["text.color"])
self.set_color(mpl._val_or_rc(color, "text.color"))
self.set_fontproperties(fontproperties)
self.set_usetex(usetex)
self.set_parse_math(parse_math if parse_math is not None else
mpl.rcParams['text.parse_math'])
self.set_parse_math(mpl._val_or_rc(parse_math, 'text.parse_math'))
self.set_wrap(wrap)
self.set_verticalalignment(verticalalignment)
self.set_horizontalalignment(horizontalalignment)
Expand Down