Annotate resource_server as str for some cases - #1414
Conversation
Several classes set `scopes` as a class attribute, meaning that their `resource_server` class property will evaluate to `str`, rather than `str | None`. _Technically_, this can be violated (if `scopes` is deleted from the class), but in terms of a closed system of type-safe code, the annotation is correct. An annotation without an assignment does not rebind the name, so the subclasses' `resource_server` attribute still points at the classproperty descriptor. This corrects several type-checking errors in the docs without requiring improper checks or type-ignores to provide type-safety.
derek-globus
left a comment
There was a problem hiding this comment.
I'm surprised that this narrowing is type-safe, but our CI linting demonstrates that it is.
|
I was also surprised to see it work when I tried it! 😅 A simplified form also works: class A:
x: int | str
class B(A):
x: int
reveal_type(B.x) # int!It's unquestionably a soundness hole in typing, but there are lots of those, so I'm not that surprised. other bad soundness hole tangentThere are worse things! For example, early on def f(x: float) -> None:
pass
y: int = 0
# type-checks okay! :,(
f(y)It's wrong! Many things which take floats also take ints, but not all. There are C APIs which need a And any protocol or superclass annotation which attempts to restrict the methods you use can be circumvented by the narrowing in an class P:
def plus1(self, x: int) -> int:
return x + 1
class C(P):
def __init__(self) -> None:
self.counter = 0
def incr(self, x: int) -> int:
self.counter += x
return self.counter
def only_use_mutation_free_methods(obj: P, x: int) -> int:
... # 70 lines of code go here
if isinstance(obj, C):
y = obj.incr(x)
else:
y = obj.plus1(x)
... # 30 more lines of code
return yThat means that even if you annotate it But it still works well enough to be useful! Mostly. |
Several classes set
scopesas a class attribute, meaning that theirresource_serverclass property will evaluate tostr, rather thanstr | None.Technically, this can be violated (if
scopesis deleted from the class), but in terms of a closed system of type-safe code, the annotation is correct.An annotation without an assignment does not rebind the name, so the subclasses'
resource_serverattribute still points at the classproperty descriptor.This corrects several type-checking errors in the docs without requiring improper checks or type-ignores to provide type-safety.