xref: /aosp_15_r20/external/fonttools/Tests/config_test.py (revision e1fe3e4ad2793916b15cccdc4a7da52a7e1dd0e9)
1from fontTools.misc.configTools import AbstractConfig, Options
2import pytest
3from fontTools.config import (
4    OPTIONS,
5    Config,
6    ConfigUnknownOptionError,
7    ConfigValueParsingError,
8    ConfigValueValidationError,
9)
10from fontTools.ttLib import TTFont
11
12
13def test_can_register_option():
14    MY_OPTION = Config.register_option(
15        name="tests:MY_OPTION",
16        help="Test option, value should be True or False, default = True",
17        default=True,
18        parse=lambda v: v in ("True", "true", 1, True),
19        validate=lambda v: v == True or v == False,
20    )
21
22    assert MY_OPTION.name == "tests:MY_OPTION"
23    assert (
24        MY_OPTION.help == "Test option, value should be True or False, default = True"
25    )
26    assert MY_OPTION.default == True
27    assert MY_OPTION.parse("true") == True
28    assert MY_OPTION.validate("hello") == False
29
30    ttFont = TTFont(cfg={"tests:MY_OPTION": True})
31    assert True == ttFont.cfg.get("tests:MY_OPTION")
32    assert True == ttFont.cfg.get(MY_OPTION)
33
34
35# to parametrize tests of Config mapping interface accepting either a str or Option
36@pytest.fixture(
37    params=[
38        pytest.param("fontTools.otlLib.optimize.gpos:COMPRESSION_LEVEL", id="str"),
39        pytest.param(
40            OPTIONS["fontTools.otlLib.optimize.gpos:COMPRESSION_LEVEL"], id="Option"
41        ),
42    ]
43)
44def COMPRESSION_LEVEL(request):
45    return request.param
46
47
48def test_ttfont_has_config(COMPRESSION_LEVEL):
49    ttFont = TTFont(cfg={COMPRESSION_LEVEL: 8})
50    assert 8 == ttFont.cfg.get(COMPRESSION_LEVEL)
51
52
53def test_ttfont_can_take_superset_of_fonttools_config(COMPRESSION_LEVEL):
54    # Create MyConfig with all options from fontTools.config plus some
55    my_options = Options(Config.options)
56    MY_OPTION = my_options.register("custom:my_option", "help", "default", str, any)
57
58    class MyConfig(AbstractConfig):
59        options = my_options
60
61    ttFont = TTFont(cfg=MyConfig({"custom:my_option": "my_value"}))
62    assert 0 == ttFont.cfg.get(COMPRESSION_LEVEL)
63    assert "my_value" == ttFont.cfg.get(MY_OPTION)
64
65    # but the default Config doens't know about MY_OPTION
66    with pytest.raises(ConfigUnknownOptionError):
67        TTFont(cfg={MY_OPTION: "my_value"})
68
69
70def test_no_config_returns_default_values(COMPRESSION_LEVEL):
71    ttFont = TTFont()
72    assert 0 == ttFont.cfg.get(COMPRESSION_LEVEL)
73    assert 3 == ttFont.cfg.get(COMPRESSION_LEVEL, 3)
74
75
76def test_can_set_config(COMPRESSION_LEVEL):
77    ttFont = TTFont()
78    ttFont.cfg.set(COMPRESSION_LEVEL, 5)
79    assert 5 == ttFont.cfg.get(COMPRESSION_LEVEL)
80    ttFont.cfg.set(COMPRESSION_LEVEL, 6)
81    assert 6 == ttFont.cfg.get(COMPRESSION_LEVEL)
82
83
84def test_different_ttfonts_have_different_configs(COMPRESSION_LEVEL):
85    cfg = Config({COMPRESSION_LEVEL: 5})
86    ttFont1 = TTFont(cfg=cfg)
87    ttFont2 = TTFont(cfg=cfg)
88    ttFont2.cfg.set(COMPRESSION_LEVEL, 6)
89    assert 5 == ttFont1.cfg.get(COMPRESSION_LEVEL)
90    assert 6 == ttFont2.cfg.get(COMPRESSION_LEVEL)
91
92
93def test_cannot_set_inexistent_key():
94    with pytest.raises(ConfigUnknownOptionError):
95        TTFont(cfg={"notALib.notAModule.inexistent": 4})
96
97
98def test_value_not_parsed_by_default(COMPRESSION_LEVEL):
99    # Note: value given as a string
100    with pytest.raises(ConfigValueValidationError):
101        TTFont(cfg={COMPRESSION_LEVEL: "8"})
102
103
104def test_value_gets_parsed_if_asked(COMPRESSION_LEVEL):
105    # Note: value given as a string
106    ttFont = TTFont(cfg=Config({COMPRESSION_LEVEL: "8"}, parse_values=True))
107    assert 8 == ttFont.cfg.get(COMPRESSION_LEVEL)
108
109
110def test_value_parsing_can_error(COMPRESSION_LEVEL):
111    with pytest.raises(ConfigValueParsingError):
112        TTFont(
113            cfg=Config(
114                {COMPRESSION_LEVEL: "not an int"},
115                parse_values=True,
116            )
117        )
118
119
120def test_value_gets_validated(COMPRESSION_LEVEL):
121    # Note: 12 is not a valid value for GPOS compression level (must be in 0-9)
122    with pytest.raises(ConfigValueValidationError):
123        TTFont(cfg={COMPRESSION_LEVEL: 12})
124
125
126def test_implements_mutable_mapping(COMPRESSION_LEVEL):
127    cfg = Config()
128    cfg[COMPRESSION_LEVEL] = 2
129    assert 2 == cfg[COMPRESSION_LEVEL]
130    assert list(iter(cfg))
131    assert 1 == len(cfg)
132    del cfg[COMPRESSION_LEVEL]
133    assert 0 == cfg[COMPRESSION_LEVEL]
134    assert not list(iter(cfg))
135    assert 0 == len(cfg)
136