pypyconfig/tests/test_config.py
2026-08-22 21:49:21 +02:00

231 lines
No EOL
7 KiB
Python

import pytest
import sys
from config.config import (
Config, OptionDescription, BoolOption, IntOption, FloatOption,
StrOption, ChoiceOption, ArbitraryOption, make_dict, ConfigError
)
def make_description():
gcoption = ChoiceOption('name', 'GC name', ['ref', 'framework'], 'ref')
gcdummy = BoolOption('dummy', 'dummy', default=False)
booloption = BoolOption('bool', 'Test boolean option', default=True)
intoption = IntOption('int', 'Test int option', default=0)
floatoption = FloatOption('float', 'Test float option', default=2.3)
stroption = StrOption('str', 'Test string option', default="abc")
wantref_option = BoolOption('wantref', 'Test requires', default=False,
requires=[('gc.name', 'ref')])
wantframework_option = BoolOption('wantframework', 'Test requires',
default=False,
requires=[('gc.name', 'framework')])
gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption])
descr = OptionDescription('pypy', '', [gcgroup, booloption,
wantref_option, stroption,
wantframework_option,
intoption])
return descr
def test_base_config():
descr = make_description()
config = Config(descr, bool=False)
assert config.gc.name == 'ref'
config.gc.name = 'framework'
assert config.gc.name == 'framework'
assert getattr(config, "gc.name") == 'framework'
assert config.gc.float == 2.3
assert config.int == 0
config.gc.float = 3.4
config.int = 123
assert config.gc.float == 3.4
assert config.int == 123
assert not config.wantref
assert config.str == "abc"
config.str = "def"
assert config.str == "def"
with pytest.raises(ConfigError):
config.gc.name = "foo"
with pytest.raises(AttributeError):
config.gc.foo = "bar"
with pytest.raises(ConfigError):
config.bool = 123
with pytest.raises(ConfigError):
config.int = "hello"
with pytest.raises(ConfigError):
config.gc.float = None
config = Config(descr, bool=False)
assert config.gc.name == 'ref'
config.wantframework = True
with pytest.raises(ConfigError):
config.gc.name = "ref"
config.gc.name = "framework"
def test___dir__():
descr = make_description()
config = Config(descr, bool=False)
attrs = dir(config)
assert '__repr__' in attrs # from the type
assert '_cfgimpl_values' in attrs # from self
assert 'gc' in attrs # custom attribute
attrs = dir(config.gc)
assert 'name' in attrs
assert 'dummy' in attrs
assert 'float' in attrs
def test_arbitrary_option():
descr = OptionDescription("top", "", [
ArbitraryOption("a", "no help", default=None)
])
config = Config(descr)
config.a = []
config.a.append(1)
assert config.a == [1]
descr = OptionDescription("top", "", [
ArbitraryOption("a", "no help", defaultfactory=list)
])
c1 = Config(descr)
c2 = Config(descr)
c1.a.append(1)
assert c2.a == []
assert c1.a == [1]
def test_compare_configs():
descr = make_description()
conf1 = Config(descr)
conf2 = Config(descr)
conf2.wantref = True
assert conf1 != conf2
assert conf1.getkey() != conf2.getkey()
conf1.wantref = True
assert conf1 == conf2
assert conf1.getkey() == conf2.getkey()
def test_loop():
descr = make_description()
conf = Config(descr)
for (name, value), (gname, gvalue) in \
zip(conf.gc, [("name", "ref"), ("dummy", False)]):
assert name == gname
assert value == gvalue
def test_getpaths():
descr = make_description()
config = Config(descr)
assert config.getpaths() == ['gc.name', 'gc.dummy', 'gc.float', 'bool',
'wantref', 'str', 'wantframework',
'int']
assert config.getpaths() == descr.getpaths()
assert config.gc.getpaths() == ['name', 'dummy', 'float']
assert config.gc.getpaths() == descr.gc.getpaths()
assert config.getpaths(include_groups=True) == [
'gc', 'gc.name', 'gc.dummy', 'gc.float',
'bool', 'wantref', 'str', 'wantframework', 'int']
assert config.getpaths(True) == descr.getpaths(True)
def test_underscore_in_option_name():
descr = OptionDescription("opt", "", [
BoolOption("_foobar", "", default=False),
])
config = Config(descr)
def test_requirements_from_top():
descr = OptionDescription("test", '', [
BoolOption("toplevel", "", default=False),
OptionDescription("sub", '', [
BoolOption("opt", "", default=False,
requires=[("toplevel", True)])
])
])
config = Config(descr)
config.sub.opt = True
assert config.toplevel
def test_overrides_are_defaults():
descr = OptionDescription("test", "", [
BoolOption("b1", "", default=False, requires=[("b2", False)]),
BoolOption("b2", "", default=False),
])
config = Config(descr)
config.b2 = True
assert config.b2
config.b1 = True
assert not config.b2
def test_make_dict():
descr = OptionDescription("opt", "", [
OptionDescription("s1", "", [
BoolOption("a", "", default=False)]),
IntOption("int", "", default=42)])
config = Config(descr)
d = make_dict(config)
assert d == {"s1.a": False, "int": 42}
config.int = 43
config.s1.a = True
d = make_dict(config)
assert d == {"s1.a": True, "int": 43}
def test_copy():
descr = OptionDescription("opt", "", [
OptionDescription("s1", "", [
BoolOption("a", "", default=False)]),
IntOption("int", "", default=42)])
c1 = Config(descr)
c1.int = 43
c2 = c1.copy()
assert c2.int == 43
assert not c2.s1.a
c2.s1.a = True
assert c2.s1.a
with pytest.raises(ConfigError):
c2.int = 44
c2 = c1.copy(as_default=True)
assert c2.int == 43
assert not c2.s1.a
c2.s1.a = True
assert c2.s1.a
c2.int = 44
def test_bool_suggests():
descr = OptionDescription("test", '', [
BoolOption("toplevel", "", default=False),
BoolOption("opt", "", default=False,
suggests=[("toplevel", True)])
])
c = Config(descr)
assert not c.toplevel
assert not c.opt
c.opt = True
assert c.opt
assert c.toplevel
c.toplevel = False
assert not c.toplevel
# Test that user-set values take precedence over suggestions
c = Config(descr)
c.toplevel = False
assert not c.toplevel
c.opt = True
assert c.opt
assert not c.toplevel
def test_delattr():
descr = OptionDescription("opt", "", [
OptionDescription("s1", "", [
BoolOption("a", "", default=False)]),
IntOption("int", "", default=42)])
c = Config(descr)
c.int = 45
assert c.int == 45
del c.int
assert c.int == 42
c.int = 45
assert c.int == 45