- 
          
- 
        Couldn't load subscription status. 
- Fork 373
attempt to add typing to _create #3260
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
base: main
Are you sure you want to change the base?
Conversation
| Codecov ReportAll modified and coverable lines are covered by tests ✅ 
 Additional details and impacted files@@               Coverage Diff               @@
##                 main        #3260   +/-   ##
===============================================
  Coverage   100.00000%   100.00000%           
===============================================
  Files             124          124           
  Lines           19047        19047           
  Branches         1287         1287           
===============================================
  Hits            19047        19047           
 🚀 New features to boost your workflow:
 | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the _create calls, I know Never often appears if mypy failed to solve the typevars, so could be an inference failure. Might be good to add reveal_type(TheClass._create) calls so we can see what mypy assumes it is.
| return super().__call__(*args, **kwargs) # type: ignore | ||
| def _create(cls: Callable[P, T], *args: P.args, **kwargs: P.kwargs) -> T: | ||
| # misc = unsupported argument 2 for "super" (??) | ||
| return super().__call__(*args, **kwargs) # type: ignore[misc,no-any-return] | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's going on here is the cls: Callable makes MyPy forget that it should require a class - NoPublicConstructor._create(lambda: 0) should function. It is useful to be able to widen self-types like that, but it means the super() call fails. I guess Mypy type-checks the 2-arg form of super() automatically?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, it's not wrong surprisingly:
>>> class Xs:
...     def f(self) -> None:
...         pass
...
>>> class X(Xs):
...     def f(self: object) -> None:
...         super().f()
...         return
...
>>> Xs().f()
>>> X().f()
>>> X.f(X())
>>> X.f(5)
Traceback (most recent call last):
  File "<python-input-7>", line 1, in <module>
    X.f(5)
    ~~~^^^
  File "<python-input-3>", line 3, in f
    super().f()
    ^^^^^^^^^
TypeError: super(type, obj): obj (instance of int) is not an instance or subtype of type (X).| 
 
 
  | 
| also if anybody wants to mess around with this PR you are very welcome, I'm not gonna put a lot of effort into it | 
| Looks like this approach doesn't handle type vars (I think that's what you're seeing): import dataclasses
from typing import Protocol, TypeVar, ParamSpec, Generic, Callable
T = TypeVar("T", covariant=True)
P = ParamSpec("P")
class Meta(type):
    def __call__(cls, *args: object, **kwargs: object) -> None:
        raise TypeError(
            f"{cls.__module__}.{cls.__qualname__} has no public constructor",
        )
    def _create(cls: Callable[P, T], *args: P.args, **kwargs: P.kwargs) -> type[T]:
        return super().__call__(*args, **kwargs)  # type: ignore
@dataclasses.dataclass
class X(Generic[T], metaclass=Meta):
    x: T
reveal_type(X._create)  # N: Revealed type is "def (*args: Never, **kwargs: Never) -> type[Never]"Surprisingly now that I see it minimized like that, I think I know exactly the bug: python/mypy#18400. I haven't checked my solution PR to make sure it has the same cause though. | 
context: #3256 (comment)
@A5rocks
remaining errors:
my hypothesis for these is that they all inherit from some other class which doesn't have this parameter, and
_createsees the super class. idk how to fix thatidk who's in the wrong here
this might be an actual bug? https://github.com/python/typeshed/blob/eec809d049d10a5ae9b88780eab15fe36a9768d7/stdlib/subprocess.pyi#L1464 for reference