From a85b3dfb2a2835bfe1f2c47a5719e2f8a001819d Mon Sep 17 00:00:00 2001 From: Florian Sesser Date: Mon, 4 Nov 2024 15:42:56 +0000 Subject: [PATCH] attrs 24 dropped 'provides()' from its API ... and provided this copypasta for people who rely on it, see https://github.com/python-attrs/attrs/pull/1265 --- src/_zkapauthorizer/_attrs_zope.py | 39 ++++++++++++++++++++++++++ src/_zkapauthorizer/_storage_client.py | 2 +- src/_zkapauthorizer/_storage_server.py | 3 +- 3 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 src/_zkapauthorizer/_attrs_zope.py diff --git a/src/_zkapauthorizer/_attrs_zope.py b/src/_zkapauthorizer/_attrs_zope.py new file mode 100644 index 00000000..efda9568 --- /dev/null +++ b/src/_zkapauthorizer/_attrs_zope.py @@ -0,0 +1,39 @@ +import attrs + +@attrs.define(repr=False) +class _ProvidesValidator: + interface = attrs.field() + + def __call__(self, inst, attr, value): + """ + We use a callable class to be able to change the ``__repr__``. + """ + if not self.interface.providedBy(value): + msg = f"'{attr.name}' must provide {self.interface!r} which {value!r} doesn't." + raise TypeError( + msg, + attr, + self.interface, + value, + ) + + def __repr__(self): + return f"" + + +def provides(interface): + """ + A validator that raises a `TypeError` if the initializer is called + with an object that does not provide the requested *interface* (checks are + performed using ``interface.providedBy(value)`` (see `zope.interface + `_). + + :param interface: The interface to check for. + :type interface: ``zope.interface.Interface`` + + :raises TypeError: With a human readable error message, the attribute + (of type `attrs.Attribute`), the expected interface, and the + value it got. + """ + return _ProvidesValidator(interface) + diff --git a/src/_zkapauthorizer/_storage_client.py b/src/_zkapauthorizer/_storage_client.py index 93085e4f..63ce9491 100644 --- a/src/_zkapauthorizer/_storage_client.py +++ b/src/_zkapauthorizer/_storage_client.py @@ -24,7 +24,6 @@ from typing import Any, Awaitable, Callable, Optional, Protocol, TypeVar from allmydata.interfaces import IStorageServer -from attr.validators import provides from attrs import Factory, define, field from foolscap.ipb import IRemoteReference from foolscap.referenceable import RemoteReference @@ -51,6 +50,7 @@ slot_testv_and_readv_and_writev_message, ) from .validators import positive_integer +from ._attrs_zope import provides _T = TypeVar("_T") _P = ParamSpec("_P") diff --git a/src/_zkapauthorizer/_storage_server.py b/src/_zkapauthorizer/_storage_server.py index 0609fc3a..7e74a439 100644 --- a/src/_zkapauthorizer/_storage_server.py +++ b/src/_zkapauthorizer/_storage_server.py @@ -59,7 +59,7 @@ from allmydata.storage.server import StorageServer from allmydata.storage.shares import get_share_file from allmydata.util.base32 import b2a -from attr.validators import instance_of, provides +from attr.validators import instance_of from attrs import field, frozen from challenge_bypass_ristretto import ( PublicKey, @@ -94,6 +94,7 @@ slot_testv_and_readv_and_writev_message, ) from .validators import positive_integer +from ._attrs_zope import provides # See allmydata/storage/mutable.py SLOT_HEADER_SIZE = 468