ruff/crates/ruff_linter/resources/test/fixtures/pyflakes/F821_17.py

118 lines
3.6 KiB
Python

"""Test type parameters and aliases"""
# Type parameters in type alias statements
from some_module import Bar
type Foo[T] = T # OK
type Foo[T] = list[T] # OK
type Foo[T: ForwardA] = T # OK
type Foo[*Ts] = Bar[Ts] # OK
type Foo[**P] = Bar[P] # OK
class ForwardA: ...
# Types used in aliased assignment must exist
type Foo = DoesNotExist # F821: Undefined name `DoesNotExist`
type Foo = list[DoesNotExist] # F821: Undefined name `DoesNotExist`
# Type parameters do not escape alias scopes
type Foo[T] = T
T # F821: Undefined name `T` - not accessible afterward alias scope
# Type parameters in functions
def foo[T](t: T) -> T: return t # OK
async def afoo[T](t: T) -> T: return t # OK
def with_forward_ref[T: ForwardB](t: T) -> T: return t # OK
def can_access_inside[T](t: T) -> T: # OK
print(T) # OK
return t # OK
class ForwardB: ...
# Type parameters do not escape function scopes
from some_library import some_decorator
@some_decorator(T) # F821: Undefined name `T` - not accessible in decorators
def foo[T](t: T) -> None: ...
T # F821: Undefined name `T` - not accessible afterward function scope
# Type parameters in classes
class Foo[T](list[T]): ... # OK
class UsesForward[T: ForwardC](list[T]): ... # OK
class ForwardC: ...
class WithinBody[T](list[T]): # OK
t = T # OK
x: T # OK
def foo(self, x: T) -> T: # OK
return x
def foo(self):
T # OK
# Type parameters do not escape class scopes
from some_library import some_decorator
@some_decorator(T) # F821: Undefined name `T` - not accessible in decorators
class Foo[T](list[T]): ...
T # F821: Undefined name `T` - not accessible after class scope
# Types specified in bounds should exist
type Foo[T: DoesNotExist] = T # F821: Undefined name `DoesNotExist`
def foo[T: DoesNotExist](t: T) -> T: return t # F821: Undefined name `DoesNotExist`
class Foo[T: DoesNotExist](list[T]): ... # F821: Undefined name `DoesNotExist`
type Foo[T: (DoesNotExist1, DoesNotExist2)] = T # F821: Undefined name `DoesNotExist1`, Undefined name `DoesNotExist2`
def foo[T: (DoesNotExist1, DoesNotExist2)](t: T) -> T: return t # F821: Undefined name `DoesNotExist1`, Undefined name `DoesNotExist2`
class Foo[T: (DoesNotExist1, DoesNotExist2)](list[T]): ... # F821: Undefined name `DoesNotExist1`, Undefined name `DoesNotExist2`
# Same in defaults
type Foo[T = DoesNotExist] = T # F821: Undefined name `DoesNotExist`
def foo[T = DoesNotExist](t: T) -> T: return t # F821: Undefined name `DoesNotExist`
class Foo[T = DoesNotExist](list[T]): ... # F821: Undefined name `DoesNotExist`
type Foo[T = (DoesNotExist1, DoesNotExist2)] = T # F821: Undefined name `DoesNotExist1`, Undefined name `DoesNotExist2`
def foo[T = (DoesNotExist1, DoesNotExist2)](t: T) -> T: return t # F821: Undefined name `DoesNotExist1`, Undefined name `DoesNotExist2`
class Foo[T = (DoesNotExist1, DoesNotExist2)](list[T]): ... # F821: Undefined name `DoesNotExist1`, Undefined name `DoesNotExist2`
# Type parameters in nested classes
class Parent[T]:
t = T # OK
def can_use_class_variable(self, x: t) -> t: # OK
return x
class Child:
def can_access_parent_type_parameter(self, x: T) -> T: # OK
T # OK
return x
def cannot_access_parent_variable(self, x: t) -> t: # F821: Undefined name `T`
t # F821: Undefined name `t`
return x
# Type parameters in nested functions
def can_access_inside_nested[T](t: T) -> T: # OK
def bar(x: T) -> T: # OK
T # OK
return x
bar(t)
def cannot_access_in_default[T](t: T = T): # F821
pass