From 3bc9fe9fd6daf3fe9a1f7493f6a5c71bc4f0980a Mon Sep 17 00:00:00 2001 From: Abhishek Date: Thu, 12 Nov 2026 20:45:37 +0530 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20FIX:=20Reject=20url=5Fschemes=20?= =?UTF-8?q?classes=20that=20aren't=20a=20list=20of=20str?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- myst_parser/config/main.py | 7 +++---- tests/test_config_topmatter.py | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/myst_parser/config/main.py b/myst_parser/config/main.py index 24e2a540..4a2e646b 100644 --- a/myst_parser/config/main.py +++ b/myst_parser/config/main.py @@ -91,10 +91,9 @@ def check_url_schemes(inst: "MdParserConfig", field: dc.Field, value: Any) -> No raise TypeError( f"'{field.name}[{key}][title]' is not a string: {val['title']!r}" ) - if ( - "classes" in val - and not isinstance(val["classes"], list) - and not all(isinstance(c, str) for c in val["classes"]) + if "classes" in val and ( + not isinstance(val["classes"], list) + or not all(isinstance(c, str) for c in val["classes"]) ): raise TypeError( f"'{field.name}[{key}][classes]' is not a list of str: {val['classes']!r}" diff --git a/tests/test_config_topmatter.py b/tests/test_config_topmatter.py index 58be4461..af030a50 100644 --- a/tests/test_config_topmatter.py +++ b/tests/test_config_topmatter.py @@ -225,6 +225,29 @@ def test_the_dict_form_keeps_its_templates(self): assert warnings == [] assert config.url_schemes == {"wiki": {"url": "https://w.org/{{path}}"}} + @pytest.mark.parametrize( + "classes", + ["my-class", ["a", 1], 1], + ids=["string", "non-string-item", "int"], + ) + def test_classes_must_be_a_list_of_strings(self, classes): + """A bare string was accepted, and split into one class per character; + a list holding a non-string was accepted, and crashed the HTML writer. + """ + with pytest.raises(TypeError, match=r"\[classes\]' is not a list of str"): + MdParserConfig(url_schemes={"gh": {"url": "{{path}}", "classes": classes}}) + _config, warnings = merge( + {"myst": {"url_schemes": {"gh": {"url": "{{path}}", "classes": classes}}}} + ) + assert len(warnings) == 1 + assert "is not a list of str" in warnings[0] + + def test_classes_list_of_strings_is_accepted(self): + config = MdParserConfig( + url_schemes={"gh": {"url": "{{path}}", "classes": ["a", "b"]}} + ) + assert config.url_schemes["gh"]["classes"] == ["a", "b"] + class TestGlobalOnlyWarningKind: """The global-only rejection is a ``myst.topmatter`` warning.