attrs icon indicating copy to clipboard operation
attrs copied to clipboard

instance_of validator cannot refer to the current class

Open taliastocks opened this issue 4 years ago • 3 comments

Hi,

I'm working on a project where it's useful for an attribute to refer to the current class. Currently, I'm using something like:

from __future__ import annotations  # Needed for recursive type annotations.


@attr.s(slots=True)
class Namespace(object):
    parent: Namespace = attr.ib(
        validator=lambda inst, attr_, val: attr.validators.instance_of(Namespace)(inst, attr_, val)
    )

Is there currently a better way to do this? If not, would you be open to a pull request that might allow something like this?

validator = attr.validators.instance_of(type_getter=lambda: Namespace)

(Also, if you have other suggestions for an approach, I'd be happy to implement those in a PR instead.)

taliastocks avatar Nov 28 '20 18:11 taliastocks

May be I'm not a fan of built-in validators, but why don't use custom validator, which checks attrib.type? It's possible to resolve attrib.type with attr.resolve_types.

import attr

def validate_type(self, attrib, value):
    assert isinstance(value, attrib.type) 

@attr.dataclass 
class X: 
    instance: 'X' = attr.ib(validator=validate_type) 
    @instance.default 
    def _instance_default(self): 
        return self 

attr.resolve_types(X)

x = X()  # Works fine

x_failed = X(42)  # Raises AssertionError

UPD: Simplified example

Drino avatar Nov 29 '20 07:11 Drino

This is something that keeps coming and the problem remains the same: the behavior of using type annotations together with isinstance() is not very useful once you go beyond trivial cases. E.g. List[int] already falls short. What you really need is a proper validation framework that can act on it and you can find a bunch of those in our wiki.

hynek avatar Nov 29 '20 08:11 hynek

@hynek so… out of scope for attrs…?

wsanchez avatar Jan 28 '21 19:01 wsanchez