Last active
December 22, 2021 23:40
-
-
Save nfitzen/d3f9aaf17acda34c37452b528d060fa8 to your computer and use it in GitHub Desktop.
A Python decorator that makes a class immutable after initialization.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# SPDX-License-Identifier: MIT | |
# SPDX-FileNotice: The Expat/MIT variant is the one without the "next paragraph" parenthetical but with the "MIT License" header. | |
# Copyright (C) 2021 nfitzen <https://github.com/nfitzen> | |
# Note that this code is very basic and likely buggy, as with everything I | |
# write. Specifically, the help message is a bit weird and slightly inaccurate. | |
import functools | |
from typing import Any | |
__all__ = ( | |
"FrozenInstanceError", | |
"frozen", | |
) | |
class FrozenInstanceError(AttributeError): | |
pass | |
def frozen(cls: type) -> type: | |
"""Freezes an object after calling its __init__ method.""" | |
def setat(self, name: str, value: Any) -> None: | |
"""Raises FrozenInstanceError after initialization.""" | |
if getattr(self, "__is_frozen__", False): | |
raise FrozenInstanceError | |
object.__setattr__(self, name, value) | |
def delat(self, name: str) -> None: | |
"""Raises FrozenInstanceError after initialization.""" | |
if getattr(self, "__is_frozen__", False): | |
raise FrozenInstanceError | |
object.__delattr__(self, name) | |
@functools.wraps(cls.__init__) | |
def init(self, *args, **kwargs): | |
return_val = self.__frozen_init__(*args, **kwargs) | |
self.__is_frozen__ = True | |
return return_val | |
orig_init = cls.__init__ | |
setattr(cls, "__init__", init) | |
setattr(cls, "__frozen_init__", orig_init) | |
setattr(cls, "__delattr__", delat) | |
setattr(cls, "__setattr__", setat) | |
return cls |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment