
Security News
Open Source Maintainers Feeling the Weight of the EU’s Cyber Resilience Act
The EU Cyber Resilience Act is prompting compliance requests that open source maintainers may not be obligated or equipped to handle.
Github repo: https://github.com/clvnkhr/immutable-defaults
Simple decorator to force immutability to function arguments by deepcopying. Never again pass None
when your heart wants to pass an empty list. Also works for arbitrary objects that can be deepcopied. Has simple config options for granularity or performance (copy vs deepcopy).
No dependencies.
In order to use various type hints we require Python >=3.12.
pip install immutable-defaults
or your equivalent (e.g. pdm add immutable-defaults
)
from immutable_defaults import immutable_defaults
@immutable_defaults
def my_function(a: list = []):
a.append("world")
return a
print(my_function()) # ['world']
print(my_function(a=["hello"])) # ['hello', 'world']
print(my_function(["HELLO"])) # ['HELLO', 'world']
print(my_function()) # ['world']
@immutable_defaults(ignore=["b"])
def my_function2(a = ["hello"], b = []):
"""basic function with ignore parameter"""
a.append("world")
b.append("!")
return a + b
print(my_function2()) # ['hello', 'world', '!']
print(my_function2()) # ['hello', 'world', '!', '!']
print(my_function2()) # ['hello', 'world', '!', '!', '!']
# more exhaustive tests in tests/tests.py
The decorator works with methods, classmethods and staticmethods. Since @immutable_defaults
requires that the wrapped function is callable
, make sure that the outer decorator is @classmethod
/@staticmethod
.
@immutable_defaults
can be called with keyword arguments deepcopy
and ignore
.
deepcopy: boolean | Iterable[str] = True
True
then defaults are copied with copy.deepcopy
. If False, then with copy.copy
.a
and arg
will be deep copied while b
will be shallow copied. @immutable_defaults(deepcopy=["a","arg"])
def f(a=[[1]], b=[], arg={1: {2}}): ...
ignore: Iterable[str] | None = None
a is b
comparison) marked for both shallow and deep copying. For example, the below will raise an ImmutableDefaultsError
:xss = [[1]]
@immutable_defaults(deepcopy=["xss2"]) # raises ImmutableDefaultsError
def f(x, xss1 = xss, xss2 = xss): ...
ImmutableDefaultsError
:xss = [[1]]
@immutable_defaults(ignore=["xss2"]) # raises ImmutableDefaultsError
def f(x, xss1 = xss, xss2 = xss): ...
KeyError
is raised if either deepcopy
or ignore
have arguments that cannot be found in the signature of the decorated function.
ignore
are not present, but this would make typos very hard to debug.ignore
takes precedence over deepcopy
, i.e. @immutable_defaults(ignore=["x"], deepcopy=["x"])
will do the same thing as @immutable_defaults(ignore=["x"])
(Comments valid May 13 2024)
__deepcopy__
(or optionally __copy__
).FAQs
Immutable defaults for Python
We found that immutable-defaults demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
The EU Cyber Resilience Act is prompting compliance requests that open source maintainers may not be obligated or equipped to handle.
Security News
Crates.io adds Trusted Publishing support, enabling secure GitHub Actions-based crate releases without long-lived API tokens.
Research
/Security News
Undocumented protestware found in 28 npm packages disrupts UI for Russian-language users visiting Russian and Belarusian domains.