[Python] How to issue warnings from a `attrs` validator with correct `stacklevel`?

Discussão em 'Python' iniciado por Stack, Março 20, 2025.

  1. Stack

    Stack Membro Participativo

    I want to use validators to issue warnings for notable but non-catastrophic issues on classes. However, by default warnings will point to the place where the warning was defined, and I want to have the warning point to the piece of user code where the warning was issued from:

    import attrs
    import warnings

    valid_names = ["a", "b", "c"]

    @attrs.define
    class Example:
    name: str = attrs.field()

    @name.validator
    def ensure_name_valid(self, attribute, value):
    if value not in valid_names:
    warnings.warn("'name' not a valid name") # <- Warning points here

    e = Example(name="x") # <- Warning should point here
    e.name = "y" # <- Warning should point here


    Classically you would use stacklevel=... when issuing the warning, but I cannot do that here because the constructor and attribute setting require different values for stacklevel. Perhaps it could be dynamically set if there was some way to introspect from what context the validator was running, but even if this is possible, to me it seems like an anti-pattern. The only other option I can think of is to catch_warnings from the function that calls the validator, but I don't really want to monkeypatch attrs's internals. What can I do instead?

    (If not possible with Python warnings but possible with some other method, I'll take alternatives.)

    Continue reading...

Compartilhe esta Página