You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[1.16 regression] descriptor not working in protocol #19054
This was an intentional change, to make descriptor access more consistent, see this PR comment for more motivation #18831 (comment). IMO the code in the example is a bug, such pattern should be reserved for when the actual attribute type is a descriptor, otherwise one should just use path: str in the protocol.
Ok, let me play around with this a little. The impact to the Dropbox internal codebase (where I found this) is very minor, so if using path: str works, we can close this issue.
I couldn't find a way to make a concrete class that uses the descriptor to be compatible with the protocol:
importtypingA=typing.TypeVar('A')
classAttribute(typing.Generic[A]):
@typing.overloaddef__get__(self, instance: None, owner: typing.Any) ->Attribute[A]: ...
@typing.overloaddef__get__(self, instance: object, owner: typing.Any) ->A: ...
def__get__(self, instance, owner): ...
classPathArg(typing.Protocol):
@property# Attempt to use @property since the descriptor is read onlydefpath(self) ->str: ...
classC:
path=Attribute[str]()
deff(arg: PathArg) ->None:
s: str=arg.pathdefg(c: C) ->None:
reveal_type(c.path) # "str", as expectedf(c) # error: C is not compatible with PathArg <<-- this should be fine?
Is there a way to modify the old example so that it works using the new semantics?
OK, I understand what happened (i.e. why someone defined such weird protocol). The problem is that protocols never worked with descriptors, see #5481, so someone found this workaround, and now this workaround doesn't work anymore.
I think the best way forward is to just wait for the proper descriptor support added in #18943. I you are really worried about this, you can revert it in the release branch. But I wouldn't bother, because IMO this is really niche workaround.
This only impacts two files in the Dropbox codebase, so it's not a big deal. As you said, the code is kind of questionable anyway, so this shouldn't block the release.
This is a big issue for us. We have a system where we use dataclasses with a special descriptor field to define schemas. Since there's no common base class, we use a protocol to type "generic schema".
to correctly specify the interface. This works on current master. This means however that you may need to wait for the next release for this to be available. Anyway, I don't think we need to keep this open, the old behavior was wrong.
@ilevkivskyi That's simply wrong. It does not work when using the type. For example:
ST=TypeVar("ST", bound=HasDesc)
defread_schema(cls: type[ST]) ->ST:
print(cls.desc) # use desc to read
TBH I don't see how the current behavior is defensible. It makes Protocols inconsistent with regular classes and it contradicts the runtime. Please fix.
Activity
ilevkivskyi commentedon May 8, 2025
This was an intentional change, to make descriptor access more consistent, see this PR comment for more motivation #18831 (comment). IMO the code in the example is a bug, such pattern should be reserved for when the actual attribute type is a descriptor, otherwise one should just use
path: strin the protocol.JukkaL commentedon May 8, 2025
Ok, let me play around with this a little. The impact to the Dropbox internal codebase (where I found this) is very minor, so if using
path: strworks, we can close this issue.JukkaL commentedon May 9, 2025
I couldn't find a way to make a concrete class that uses the descriptor to be compatible with the protocol:
Is there a way to modify the old example so that it works using the new semantics?
JukkaL commentedon May 9, 2025
Another use case where the new behavior may cause issues is when using
type[PathArg]-- herepath: Attribute[str]in the protocol makes a difference:ilevkivskyi commentedon May 9, 2025
OK, I understand what happened (i.e. why someone defined such weird protocol). The problem is that protocols never worked with descriptors, see #5481, so someone found this workaround, and now this workaround doesn't work anymore.
I think the best way forward is to just wait for the proper descriptor support added in #18943. I you are really worried about this, you can revert it in the release branch. But I wouldn't bother, because IMO this is really niche workaround.
JukkaL commentedon May 9, 2025
This only impacts two files in the Dropbox codebase, so it's not a big deal. As you said, the code is kind of questionable anyway, so this shouldn't block the release.
eltoder commentedon Jun 9, 2025
This is a big issue for us. We have a system where we use dataclasses with a special descriptor field to define schemas. Since there's no common base class, we use a protocol to type "generic schema".
ilevkivskyi commentedon Jun 9, 2025
@eltoder I have two questions:
eltoder commentedon Jun 10, 2025
@ilevkivskyi
[-]Regression: descriptor not working in protocol[/-][+][1.16 regression] descriptor not working in protocol[/+]ilevkivskyi commentedon Jun 10, 2025
@eltoder Then you should use this instead
to correctly specify the interface. This works on current master. This means however that you may need to wait for the next release for this to be available. Anyway, I don't think we need to keep this open, the old behavior was wrong.
eltoder commentedon Jun 10, 2025
@ilevkivskyi That's simply wrong. It does not work when using the type. For example:
TBH I don't see how the current behavior is defensible. It makes Protocols inconsistent with regular classes and it contradicts the runtime. Please fix.
ilevkivskyi commentedon Jun 10, 2025
@eltoder It is not for you to decide. Also please watch your tone.
Protocolwhich v1.15.0 supports #19274 as a duplicate of this issue