1 | """ |
---|
2 | Utilities related to attrs |
---|
3 | |
---|
4 | Handling for zope.interface is deprecated in attrs so we copy the |
---|
5 | relevant support method here since we depend on zope.interface anyway |
---|
6 | """ |
---|
7 | |
---|
8 | from attr._make import attrs, attrib |
---|
9 | |
---|
10 | |
---|
11 | @attrs(repr=False, slots=True, hash=True) |
---|
12 | class _ProvidesValidator: |
---|
13 | interface = attrib() |
---|
14 | |
---|
15 | def __call__(self, inst, attr, value): |
---|
16 | """ |
---|
17 | We use a callable class to be able to change the ``__repr__``. |
---|
18 | """ |
---|
19 | if not self.interface.providedBy(value): |
---|
20 | raise TypeError( |
---|
21 | "'{name}' must provide {interface!r} which {value!r} " |
---|
22 | "doesn't.".format( |
---|
23 | name=attr.name, interface=self.interface, value=value |
---|
24 | ), |
---|
25 | attr, |
---|
26 | self.interface, |
---|
27 | value, |
---|
28 | ) |
---|
29 | |
---|
30 | def __repr__(self): |
---|
31 | return "<provides validator for interface {interface!r}>".format( |
---|
32 | interface=self.interface |
---|
33 | ) |
---|
34 | |
---|
35 | |
---|
36 | def provides(interface): |
---|
37 | """ |
---|
38 | A validator that raises a `TypeError` if the initializer is called |
---|
39 | with an object that does not provide the requested *interface* (checks are |
---|
40 | performed using ``interface.providedBy(value)`` (see `zope.interface |
---|
41 | <https://zopeinterface.readthedocs.io/en/latest/>`_). |
---|
42 | |
---|
43 | :param interface: The interface to check for. |
---|
44 | :type interface: ``zope.interface.Interface`` |
---|
45 | |
---|
46 | :raises TypeError: With a human readable error message, the attribute |
---|
47 | (of type `attrs.Attribute`), the expected interface, and the |
---|
48 | value it got. |
---|
49 | """ |
---|
50 | return _ProvidesValidator(interface) |
---|