From 7c378a8f3f30ce57c874a851f3af8af58f1ffdf6 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Thu, 3 Mar 2022 03:19:08 +0100 Subject: [PATCH] Support quoted strings in matplotlibrc This enables using the comment character # within strings. Closes #19288. Superseeds #22565. --- .../next_whats_new/double_quotes_matplolibrc.rst | 10 ++++++++++ lib/matplotlib/__init__.py | 4 +++- lib/matplotlib/cbook/__init__.py | 15 +++++++++++++++ lib/matplotlib/mpl-data/matplotlibrc | 15 ++++++++++----- lib/matplotlib/tests/test_cbook.py | 16 ++++++++++++++++ 5 files changed, 54 insertions(+), 6 deletions(-) create mode 100644 doc/users/next_whats_new/double_quotes_matplolibrc.rst diff --git a/doc/users/next_whats_new/double_quotes_matplolibrc.rst b/doc/users/next_whats_new/double_quotes_matplolibrc.rst new file mode 100644 index 000000000000..e40c1be750b2 --- /dev/null +++ b/doc/users/next_whats_new/double_quotes_matplolibrc.rst @@ -0,0 +1,10 @@ +Double-quoted strings in matplotlibrc +------------------------------------- + +You can now use double-quotes around strings. This allows using the '#' +character in strings. Without quotes, '#' is interpreted as start of a comment. +In particular, you can now define hex-colors: + +.. code-block:: none + + grid.color: "#b0b0b0" diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py index 4663ce58636a..3dbf09a3f12c 100644 --- a/lib/matplotlib/__init__.py +++ b/lib/matplotlib/__init__.py @@ -780,7 +780,7 @@ def _rc_params_in_file(fname, transform=lambda x: x, fail_on_error=False): try: for line_no, line in enumerate(fd, 1): line = transform(line) - strippedline = line.split('#', 1)[0].strip() + strippedline = cbook._strip_comment(line) if not strippedline: continue tup = strippedline.split(':', 1) @@ -791,6 +791,8 @@ def _rc_params_in_file(fname, transform=lambda x: x, fail_on_error=False): key, val = tup key = key.strip() val = val.strip() + if val.startswith('"') and val.endswith('"'): + val = val[1:-1] # strip double quotes if key in rc_temp: _log.warning('Duplicate key in file %r, line %d (%r)', fname, line_no, line.rstrip('\n')) diff --git a/lib/matplotlib/cbook/__init__.py b/lib/matplotlib/cbook/__init__.py index c2f6062d717b..61441a1e0331 100644 --- a/lib/matplotlib/cbook/__init__.py +++ b/lib/matplotlib/cbook/__init__.py @@ -400,6 +400,21 @@ def strip_math(s): return s +def _strip_comment(s): + """Strip everything from the first unquoted #.""" + pos = 0 + while True: + quote_pos = s.find('"', pos) + hash_pos = s.find('#', pos) + if quote_pos < 0: + without_comment = s if hash_pos < 0 else s[:hash_pos] + return without_comment.strip() + elif 0 <= hash_pos < quote_pos: + return s[:hash_pos].strip() + else: + pos = s.find('"', quote_pos + 1) + 1 # behind closing quote + + def is_writable_file_like(obj): """Return whether *obj* looks like a file object with a *write* method.""" return callable(getattr(obj, 'write', None)) diff --git a/lib/matplotlib/mpl-data/matplotlibrc b/lib/matplotlib/mpl-data/matplotlibrc index 106d881ce88c..5c1625e61729 100644 --- a/lib/matplotlib/mpl-data/matplotlibrc +++ b/lib/matplotlib/mpl-data/matplotlibrc @@ -33,10 +33,15 @@ ## Colors: for the color values below, you can either use ## - a Matplotlib color string, such as r, k, or b ## - an RGB tuple, such as (1.0, 0.5, 0.0) -## - a hex string, such as ff00ff +## - a double-quoted hex string, such as "#ff00ff". +## The unquoted string ff00ff is also supported for backward +## compatibility, but is discouraged. ## - a scalar grayscale intensity such as 0.75 ## - a legal html color name, e.g., red, blue, darkslategray ## +## String values may optionally be enclosed in double quotes, which allows +## using the comment character # in the string. +## ## Matplotlib configuration are currently divided into following parts: ## - BACKENDS ## - LINES @@ -506,10 +511,10 @@ ## *************************************************************************** ## * GRIDS * ## *************************************************************************** -#grid.color: b0b0b0 # grid color -#grid.linestyle: - # solid -#grid.linewidth: 0.8 # in points -#grid.alpha: 1.0 # transparency, between 0.0 and 1.0 +#grid.color: "#b0b0b0" # grid color +#grid.linestyle: - # solid +#grid.linewidth: 0.8 # in points +#grid.alpha: 1.0 # transparency, between 0.0 and 1.0 ## *************************************************************************** diff --git a/lib/matplotlib/tests/test_cbook.py b/lib/matplotlib/tests/test_cbook.py index dcb855f73ce7..33ed3c2beaf1 100644 --- a/lib/matplotlib/tests/test_cbook.py +++ b/lib/matplotlib/tests/test_cbook.py @@ -408,6 +408,22 @@ def test_func2(): cb.process("test2") +@pytest.mark.parametrize('line, result', [ + ('a : no_comment', 'a : no_comment'), + ('a : "quoted str"', 'a : "quoted str"'), + ('a : "quoted str" # comment', 'a : "quoted str"'), + ('a : "#000000"', 'a : "#000000"'), + ('a : "#000000" # comment', 'a : "#000000"'), + ('a : ["#000000", "#FFFFFF"]', 'a : ["#000000", "#FFFFFF"]'), + ('a : ["#000000", "#FFFFFF"] # comment', 'a : ["#000000", "#FFFFFF"]'), + ('a : val # a comment "with quotes"', 'a : val'), + ('# only comment "with quotes" xx', ''), +]) +def test_strip_comment(line, result): + """Strip everything from the first unqouted #.""" + assert cbook._strip_comment(line) == result + + def test_sanitize_sequence(): d = {'a': 1, 'b': 2, 'c': 3} k = ['a', 'b', 'c']