pyright
pyright copied to clipboard
Incorrect "variable is not accessed" message
Environment data
- Language Server version: 2024.8.1
- OS and version: win32 x64
- Python version (and distribution if applicable, e.g. Anaconda): Python 3.8.10, in venv
- python.analysis.indexing: true
- python.analysis.typeCheckingMode: strict
Code Snippet
# pyright: strict
from functools import partial
from dataclasses import dataclass
@dataclass
class Dog:
name: str
breed: str
def partial_dog(breed: str):
formatted_breed = breed.title() # error: Variable "formatted_breed" is not accessed
return partial(
Dog,
breed=f"Maybe a {formatted_breed}", # but it's accessed right here
)
if __name__ == "__main__":
print(partial_dog("beagle")(name="Buddy"))
C:\Users\jdayton\source\temp> python .\repro.py
Dog(name='Buddy', breed='Maybe a Beagle')
Expected behavior
When using a function-local variable in an f-string as a dataclass
constructor argument in functools.partial
, Pylance should recognize that the variable is being accessed.
Actual behavior
Pylance reports the function-local variable as unused.
We get the same error when running pyright (pyright==1.1.377
, installed with pip) in the terminal:
C:\Users\jdayton\source\temp> pyright .\repro.py
c:\Users\jdayton\source\temp\repro.py
c:\Users\jdayton\source\temp\repro.py:11:5 - error: Variable "formatted_breed" is not accessed (reportUnusedVariable)
1 error, 0 warnings, 0 informations
We also get this error if Dog
is a pydantic BaseModel
:
from pydantic import BaseModel # pydantic==2.7.4
class Dog(BaseModel):
name: str
breed: str
We don't get this error if Dog
is a regular class:
class Dog:
def __init__(self, name: str, breed: str):
self.name = name
self.breed = breed
We also don't get the error if formatted_breed
is passed in directly, not in an f-string:
def partial_dog(breed: str):
formatted_breed = f"Maybe a {breed.title()}"
return partial(
Dog,
breed=formatted_breed,
)
If the variable in the f-string is a parameter instead of a local variable, we don't get this error, but Pylance sometimes can't tell what its type is: