diff options
author | pennae <github@quasiparticle.net> | 2023-02-19 01:33:36 +0100 |
---|---|---|
committer | pennae <github@quasiparticle.net> | 2023-02-21 18:26:40 +0100 |
commit | a7c25bb01f2373eb1f113272731e1659bc91de95 (patch) | |
tree | 3654ad672f5fa0f4f053e6d2ea4980406ebc7884 /pkgs/tools/nix/nixos-render-docs | |
parent | 2ab8e742a541659baa0470e3be8fc7e01ff51175 (diff) | |
download | nixpkgs-a7c25bb01f2373eb1f113272731e1659bc91de95.tar nixpkgs-a7c25bb01f2373eb1f113272731e1659bc91de95.tar.gz nixpkgs-a7c25bb01f2373eb1f113272731e1659bc91de95.tar.bz2 nixpkgs-a7c25bb01f2373eb1f113272731e1659bc91de95.tar.lz nixpkgs-a7c25bb01f2373eb1f113272731e1659bc91de95.tar.xz nixpkgs-a7c25bb01f2373eb1f113272731e1659bc91de95.tar.zst nixpkgs-a7c25bb01f2373eb1f113272731e1659bc91de95.zip |
nixos-render-docs: add Freezable class
for most of our data classes we can use dataclasses.dataclass with frozen=True or even plain named tuples. the TOC structure we'll need to generate proper navigation links is most easily represented and used as a cyclic structure though, and for that we can use neither. if we want to make the TOC structures immutable (which seems like a good idea) we'll need a hack of *some* kind, and this hack seems like the least intrusive.
Diffstat (limited to 'pkgs/tools/nix/nixos-render-docs')
-rw-r--r-- | pkgs/tools/nix/nixos-render-docs/src/nixos_render_docs/utils.py | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/pkgs/tools/nix/nixos-render-docs/src/nixos_render_docs/utils.py b/pkgs/tools/nix/nixos-render-docs/src/nixos_render_docs/utils.py new file mode 100644 index 00000000000..3377d1fa4fe --- /dev/null +++ b/pkgs/tools/nix/nixos-render-docs/src/nixos_render_docs/utils.py @@ -0,0 +1,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 |