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

Feature: Generate .pyi files #10

Open
ronaldoussoren opened this issue Aug 26, 2020 · 1 comment
Open

Feature: Generate .pyi files #10

ronaldoussoren opened this issue Aug 26, 2020 · 1 comment
Labels
enhancement New feature or request

Comments

@ronaldoussoren
Copy link
Owner

This first needs a design, but it should be possible to generate .pyi files for mypy and code completion.

The hard part is how to represent objective protocols, those aren't named objects in the bindings and aren't really types. This might need a mypy plugin...

Mypy doesn't understand metaclasses, and especially not those implemented in C. A good enough solution is to use regular classes in the stub files, with "@classmethod" decorators for class methods. This causes a conflict when a class has both a class and instance method of the same name, but there shouldn't be many of those.

One other possible issue: the generated files will be huge (and will get larger when the annotations get more precise), I have no idea if that will cause problems.

@ronaldoussoren ronaldoussoren added the enhancement New feature or request label Aug 26, 2020
@glyph
Copy link

glyph commented Mar 28, 2023

This causes a conflict when a class has both a class and instance method of the same name, but there shouldn't be many of those.

You can avoid this conflict by simply omitting the instance method when a class method of the same name is present; in Python you can happily call class methods on instances, so mypy will see nothing wrong with it.

If there are truly pathological cases where the methods have the same name but different types, it can even be coerced to typecheck that, with a minor hack like this (python, not pyi here, just so that you can see the interaction with the implementation, but the same principle applies):

from __future__ import annotations
from typing import ClassVar, Protocol, overload


class InstanceSignature(Protocol):
    def __call__(self, arg: int) -> None:
        ...


class ClassSignature(Protocol):
    def __call__(self, arg: str) -> None:
        ...


class BothMethod:
    @overload
    def __get__(self, instance: None, owner=None) -> ClassSignature:
        ...

    @overload
    def __get__(self, instance: Foo, owner=None) -> InstanceSignature:
        ...

    def __get__(
        self, instance: Foo | None, owner=None
    ) -> ClassSignature | InstanceSignature:
        ...
        instanceMethod: InstanceSignature
        classMethod: ClassSignature

        if instance is None:
            return instanceMethod
        else:
            return classMethod


class Foo:
    method: ClassVar[BothMethod]


f = Foo()
f.method(3)
Foo.method("name")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants