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...