Pyright: cannot assign class instance to protocol type

Created on 8 Feb 2020  路  4Comments  路  Source: microsoft/pyright

Describe the bug

In this example, I am assigning an instance of a class that looks like it meets a protocol to a variable tagged with that protocol:

from typing import Protocol

class Distribution(Protocol):
    @property
    def batch_shape(self) -> int:
        return 0


class MockDistribution:
    def __init__(self, batch_shape: int):
        self._batch_shape = batch_shape

    @property
    def batch_shape(self) -> int:
        return self._batch_shape


d: Distribution = MockDistribution(batch_shape=1)

This fails with the following error:

pyright --project misc\pyright_test\pyright_test21\pyrightconfig.json 
Loading configuration file at C:\p\misc\pyright_test\pyright_test21\pyrightconfig.json
Auto-excluding **/node_modules
Auto-excluding **/__pycache__
Auto-excluding .venv
Auto-excluding .git
typingsPath C:\p\misc\pyright_test\pyright_test21\typings is not a valid directory.
Searching for source files
Found 1 source file
C:\p\misc\pyright_test\pyright_test21\test.py
  73:19 - error: Expression of type 'MockDistribution' cannot be assigned to declared type 'Distribution'
  'batch_shape' is an incompatible type
    'int' is incompatible with 'int'
1 error, 0 warnings
Completed in 1.221sec

To Reproduce
Run pyright on the above code.

Expected behavior

I didn't expect this error, but I can't tell if I'm missing something about protocols that would make this not work.

VS Code extension or command-line

pyright --version
pyright 1.1.21
addressed in next version bug

Most helpful comment

Thanks for the bug report. This will be fixed in the next version of pyright.

All 4 comments

Just ran into this myself... for me, the error is specific to the use of @property decorators:

This fails:

from typing import Protocol

class ProvidesName(Protocol):
    @property
    def name(self) -> str: ...

class Lucky:
    @property
    def name(self) -> str:
        return "Lucky"

name: ProvidesName = Lucky()  # Error: 'str' is incompatible with 'str

Screen Shot 2020-02-14 at 7 05 06 AM

but it works fine if you remove the @property decorator:

from typing import Protocol

class ProvidesName(Protocol):
    def name(self) -> str: ...

class Lucky:
    def name(self) -> str:
        return "Lucky"

name: ProvidesName = Lucky()

Thanks for the bug report. This will be fixed in the next version of pyright.

This is fixed in Pyright 1.1.22, which I just published.

Thank you!

Was this page helpful?
0 / 5 - 0 ratings