Reject invalid updates in a small UserDict wrapper

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}

Comments

Popular posts from this blog

Compare Two Text Files in Python Without Modifying Them

Seven CSV Quality Checks to Run Before Importing Data

Explain why SQLite transactions cannot make an HTTP call atomic