from __future__ import annotations

import sys

if sys.version_info >= (3, 9):
    from functools import cached_property as cached_property
else:
    from typing import Any, TypeVar, Callable

    _T = TypeVar("_T")

    class cached_property:  # type: ignore[no-redef]
        """Backport for Python < 3.9."""

        def __init__(self, func: Callable[..., _T]) -> None:
            self.func = func
            self.attrname: str | None = None
            self.__doc__ = func.__doc__

        def __set_name__(self, owner: type, name: str) -> None:
            self.attrname = name

        def __get__(self, instance: Any, owner: type | None = None) -> _T:
            if instance is None:
                return self  # type: ignore[return-value]
            name = self.attrname
            assert name is not None
            try:
                return instance.__dict__[name]
            except KeyError:
                val = self.func(instance)
                instance.__dict__[name] = val
                return val
