Skip to content

ConfigBox

Chris Griffith edited this page Nov 4, 2026 · 2 revisions

A Box with additional handling of string manipulation generally found in config files.

test_config.ini

[General]
example=A regular string

[Examples]
my_bool=yes
anint=234
exampleList=234,123,234,543
floatly=4.4

With the combination of reusables and ConfigBox you can easily read python config values into python types. It supports list, bool, int and float.

import reusables
from box import ConfigBox

config = ConfigBox(reusables.config_dict("test_config.ini"))
# <ConfigBox: {'General': {'example': 'A regular string'},
# 'Examples': {'my_bool': 'yes', 'anint': '234', 'examplelist': '234,123,234,543', 'floatly': '4.4'}}>

config.Examples.list('examplelist')
# ['234', '123', '234', '543']

config.Examples.float('floatly')
# 4.4

Case-insensitive keys

New in 8.0.0. Before 8.0.0 only attribute access retried with a lowercased name.

Like configparser options, ConfigBox string keys are case-insensitive. Every kind of access finds a key whatever its case: [], attribute access, in, get, del, pop, the conversion helpers such as .int(), and box_dots paths. Nested boxes are ConfigBox objects too, so this applies at every level.

from box import ConfigBox

config = ConfigBox({"Server": {"HOST": "localhost", "Port": "8080"}})

config.server.host        # 'localhost'
config["SERVER"]["host"]  # 'localhost'
"port" in config.Server   # True
config.server.int("PORT") # 8080

The latest write wins

A ConfigBox never holds two keys that differ only by case. Writing a key that matches an existing one replaces it, and the latest write always wins: both its value and its spelling are kept, and the key moves to the end like a new key.

ConfigBox({"Foo": 1, "foo": 2})
# ConfigBox({'foo': 2})

config = ConfigBox({"host": "a", "port": 1})
config["HOST"] = "b"
# ConfigBox({'port': 1, 'HOST': 'b'})

This is the same for construction, [] and attribute assignment, update, merge_update and the | operator. merge_update still merges nested dictionaries, and the merged key takes the incoming spelling:

config = ConfigBox({"Server": {"host": "h", "port": 1}})
config.merge_update({"SERVER": {"PORT": 2}})
# ConfigBox({'SERVER': {'host': 'h', 'PORT': 2}})

Reading a key never changes its spelling, and neither does setdefault on a key that already exists.

What is not affected

  • Only str keys are matched ignoring case. Other keys, including bytes, must match exactly.
  • A regular Box is unchanged and still treats Foo and foo as different keys. Use Box if you need to keep keys that differ only by case.

Clone this wiki locally