Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pylance incorrectly assumes decorator is called without argument #2557

Closed
hmeine opened this issue Apr 11, 2022 · 2 comments
Closed

pylance incorrectly assumes decorator is called without argument #2557

hmeine opened this issue Apr 11, 2022 · 2 comments

Comments

@hmeine
Copy link

hmeine commented Apr 11, 2022

Environment data

Pylance language server 2022.4.0 (pyright 67ee16be)
Python 3.9.12 installed via MacPorts

Version: 1.66.1
Commit: 8dfae7a5cd50421d10cd99cb873990460525a898
Date: 2022-04-06T14:49:52.288Z (5 days ago)
Electron: 17.2.0
Chromium: 98.0.4758.109
Node.js: 16.13.0
V8: 9.8.177.11-electron.0
OS: Darwin arm64 21.3.0

Expected behavior

When using the @pydantic_settings.with_attrs_docs decorator, this should not affect type inference. (The decorator should just parse documentation comments into pydantic field descriptions.)

Actual behavior

VS Code reports problems with correct code (see example below), and autocompletion of the respective dataclass members does not work anymore.

The problem seems to be the if statement in the decorator being incorrectly handled; I put a more minimal example below as well.

Logs

pylance_output.txt

Code Snippet / Additional information

This example is copied from the pydantic_settings documentation:

from pydantic import BaseModel
from pydantic_settings import with_attrs_docs


@with_attrs_docs. # <==== removing this line fixes the problems
class Foo(BaseModel):
    bar: str
    """here is docs"""

    #: docs for baz
    baz: int

    #: yes
    #: of course
    is_there_multiline: bool = True


foo = Foo(bar = 'baz', baz = 42) # <==== notice that this line is incorrectly reported as error

Here is a reduced testcase without pydantic or pydantic_settings:

from typing import Any, Optional
from dataclasses import dataclass


def with_attrs_docs(model_cls: Optional[Any] = None):
    def decorator(maybe_model_cls: Any):
        return maybe_model_cls

    if model_cls is None:
        return decorator
    return decorator(model_cls)


@with_attrs_docs
@dataclass
class Foo:
    bar: str
    baz: int


foo = Foo(bar = 'baz', baz = 42)
@erictraut
Copy link
Contributor

erictraut commented Apr 11, 2022

The problem is that the pydantic_settings model is not properly annotating the decorator with_attrs_docs. It does not provide a return type annotation, so pyright (the type checker that underlies pylance) attempts to infer the return type. But return type inference is fallible.

The solution is to file a bug for the maintainers of pydantic_settings and have them properly annotate the with_attrs_docs decorator function. It will need to include generic types (a TypeVar bound to AnyPydanticModel) and overloads to hand the None case appropriately.

@hmeine
Copy link
Author

hmeine commented Apr 16, 2022

Thanks for looking into this. Your explanation makes sense to me; I think "return type inference is fallible" is a key statement here. I will follow up the the pydantic_settings project.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants