Skip to content

Commit ed95e09

Browse files
committed
update ipaddress to 3.8 equivalent
Updating ipaddress to allow fixing the referenced bug and almost-security issue with it. References: bsc#1244401 References: gh#python#128840 Depends-on: gh#openSUSE-Python/cpython@4f2496b (2024-12-02) Depends-on: gh#openSUSE-Python/cpython@2976e94 (2024-07-27) From-PR: gh#phihag/ipaddress!60 Patch: ipaddress-update-pr60.patch
1 parent 6616512 commit ed95e09

File tree

3 files changed

+740
-494
lines changed

3 files changed

+740
-494
lines changed

Lib/functools.py

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
__all__ = ['update_wrapper', 'wraps', 'WRAPPER_ASSIGNMENTS', 'WRAPPER_UPDATES',
1313
'total_ordering', 'cmp_to_key', 'lru_cache', 'reduce', 'partial',
14-
'partialmethod', 'singledispatch']
14+
'partialmethod', 'singledispatch', 'cached_property']
1515

1616
try:
1717
from _functools import reduce
@@ -814,3 +814,77 @@ def wrapper(*args, **kw):
814814
wrapper._clear_cache = dispatch_cache.clear
815815
update_wrapper(wrapper, func)
816816
return wrapper
817+
818+
################################################################################
819+
### for ipaddress
820+
### copied from https://github.com/penguinolog/backports.cached_property
821+
################################################################################
822+
"""Backport of python 3.8 functools.cached_property.
823+
824+
cached_property() - computed once per instance, cached as attribute
825+
"""
826+
# noinspection PyPep8Naming
827+
_NOT_FOUND = object()
828+
829+
class cached_property: # NOSONAR # pylint: disable=invalid-name # noqa: N801
830+
"""Cached property implementation.
831+
832+
Transform a method of a class into a property whose value is computed once
833+
and then cached as a normal attribute for the life of the instance.
834+
Similar to property(), with the addition of caching.
835+
Useful for expensive computed properties of instances
836+
that are otherwise effectively immutable.
837+
"""
838+
839+
def __init__(self, func) -> None:
840+
"""Cached property implementation."""
841+
self.func = func
842+
self.attrname = None
843+
self.__doc__ = func.__doc__
844+
self.lock = RLock()
845+
846+
def __set_name__(self, owner, name):
847+
"""Assign attribute name and owner."""
848+
if self.attrname is None:
849+
self.attrname = name
850+
elif name != self.attrname:
851+
raise TypeError(
852+
"Cannot assign the same cached_property to two different names "
853+
f"({self.attrname!r} and {name!r})."
854+
)
855+
856+
def __get__(self, instance, owner = None):
857+
"""Property-like getter implementation.
858+
859+
:return: property instance if requested on class or value/cached value if requested on instance.
860+
:rtype: Union[cached_property[self._T], self._T]
861+
:raises TypeError: call without calling __set_name__ or no '__dict__' attribute
862+
"""
863+
if instance is None:
864+
return self
865+
if self.attrname is None:
866+
raise TypeError("Cannot use cached_property instance without calling __set_name__ on it.")
867+
try:
868+
cache = instance.__dict__
869+
except AttributeError: # not all objects have __dict__ (e.g. class defines slots)
870+
msg = (
871+
f"No '__dict__' attribute on {type(instance).__name__!r} "
872+
f"instance to cache {self.attrname!r} property."
873+
)
874+
raise TypeError(msg) from None
875+
val = cache.get(self.attrname, _NOT_FOUND)
876+
if val is _NOT_FOUND:
877+
with self.lock:
878+
# check if another thread filled cache while we awaited lock
879+
val = cache.get(self.attrname, _NOT_FOUND)
880+
if val is _NOT_FOUND:
881+
val = self.func(instance)
882+
try:
883+
cache[self.attrname] = val
884+
except TypeError:
885+
msg = (
886+
f"The '__dict__' attribute on {type(instance).__name__!r} instance "
887+
f"does not support item assignment for caching {self.attrname!r} property."
888+
)
889+
raise TypeError(msg) from None
890+
return val

0 commit comments

Comments
 (0)