about summary refs log tree commit diff
path: root/nixpkgs/pkgs/tools/nix/nixos-render-docs/src/nixos_render_docs/utils.py
blob: 3377d1fa4fe18dc0193f82d185942867ac069211 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from typing import Any

_frozen_classes: dict[type, type] = {}

# make a derived class freezable (ie, disallow modifications).
# we do this by changing the class of an instance at runtime when freeze()
# is called, providing a derived class that is exactly the same except
# for a __setattr__ that raises an error when called. this beats having
# a field for frozenness and an unconditional __setattr__ that checks this
# field because it does not insert anything into the class dict.
class Freezeable:
    def freeze(self) -> None:
        cls = type(self)
        if not (frozen := _frozen_classes.get(cls)):
            def __setattr__(instance: Any, n: str, v: Any) -> None:
                raise TypeError(f'{cls.__name__} is frozen')
            frozen = type(cls.__name__, (cls,), {
                '__setattr__': __setattr__,
            })
            _frozen_classes[cls] = frozen
        self.__class__ = frozen