Batu Lab NotesPractical developer guides

Reject invalid updates in a small UserDict wrapper

By Batu ยท English technical notes

Also published in our Blogger archive.

collections.UserDict is useful when a mapping needs a narrow rule at every ordinary write. Its actual contents live in the data attribute, while its mapping methods can be customized. BoundedSettings overrides __setitem__ so construction, item assignment, and update() all pass through one validator.

The wrapper accepts only threshold and retries. Both values must have type int; using type(value) is int intentionally rejects True and False, even though booleans are subclasses of int. Thresholds are restricted to 0 through 100, and retries to 0 through 5. The invalid update({"threshold": 101}) raises ValueError before storing 101. The unknown mode key raises KeyError. The final assertion confirms that the accepted retry update did not disturb the previous threshold.

This is a small boundary around mapping writes, not a complete configuration system. UserDict.data is public; code that mutates settings.data directly bypasses __setitem__ and therefore bypasses validation. The class also does not coerce strings such as "3" to integers or provide transaction-like all-or-nothing behavior for a multi-item update if a later item fails. Add explicit parsing or a staged-copy strategy when those policies are needed.

AI assistance contributed to this draft.

Source: Python UserDict documentation

Example

from collections import UserDict


class BoundedSettings(UserDict):
    allowed = {"threshold", "retries"}

    def __setitem__(self, key, value):
        if key not in self.allowed:
            raise KeyError(f"unsupported setting: {key}")
        if type(value) is not int:
            raise TypeError("setting values must be integers")
        if key == "threshold" and not 0 <= value <= 100:
            raise ValueError("threshold must be 0..100")
        if key == "retries" and not 0 <= value <= 5:
            raise ValueError("retries must be 0..5")
        self.data[key] = value


settings = BoundedSettings({"threshold": 75, "retries": 2})

try:
    settings.update({"threshold": 101})
except ValueError as error:
    print(error)

try:
    settings["mode"] = 1
except KeyError as error:
    print(error.args[0])

settings["retries"] = 3
assert dict(settings) == {"threshold": 75, "retries": 3}
print(dict(settings))

Expected stdout

threshold must be 0..100
unsupported setting: mode
{'threshold': 75, 'retries': 3}