You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Describe the bug
I am using cloudpathlib (the latest release, 0.10.0) in one of the repos I work in. It does some interesting stuff in regard to typing. It seems to be resulting in some undefined (?) behavior.
They have an an abstract base class called cloudpathlib.AnyPath, which they register as a virtual super class of cloudpathlib.CloudPath and pathlib.Path, except that they redefine AnyPath's __new__ to return Union[CloudPath, Path].
mypy seems to think that the returned instance is an AnyPath, while pylance seems to think the returned instance is Union[CloudPath, Path].
To Reproduce
fromabcimportABCfrompathlibimportPathfromtypingimportUnion# from cloudpathlib import AnyPath, CloudPath# a minimally reproducible example ##############################classCloudPath:
def__truediv__(self, other: str) ->"CloudPath":
...
classAnyPath(ABC):
def__new__(self, *args, **kwargs) ->Union[CloudPath, Path]:
...
AnyPath.register(Path)
AnyPath.register(CloudPath)
#################################################################defupload_file(path: AnyPath) ->None:
...
cloud_path=AnyPath("s3://mybucket/myfile")
reveal_type(cloud_path) # Type of "cloud_path" is "CloudPath | Path" Pylance ; Revealed type is "a.AnyPath" mypy(note)full_path=cloud_path/".txt"# Unsupported left operand type for / ("AnyPath") [operator] mypy(error)upload_file(cloud_path) # Argument of type "CloudPath | Path" cannot be assigned to parameter "path" of type "AnyPath" in function "upload_file" Type "CloudPath | Path" cannot be assigned to type "AnyPath" ; "CloudPath" is incompatible with "AnyPath" Pylance[reportGeneralTypeIssues]
Expected behavior
Even though the current implementation is kind of strange, I don't really expect pylance's message that Cloudpath is incompatible with AnyPath since AnyPath is technically a superclass of Path and CloudPath... and I DO expect mypy's error message since typically virtual super classes define the methods that its virtual subclasses implement (which AnyPath does not).
The text was updated successfully, but these errors were encountered:
ringohoffman
changed the title
Discrepancy between pyright and mypy
Discrepancy between pyright and mypy in type evaluation of abnormal virtual super class
Dec 14, 2022
Static type checkers do not support the dynamic (runtime) registration of ABCs.
AnyPath is not a superclass of Path or CloudPath. The runtime may fake this through dynamic registration, but from a static type checking perspective, the classes have no relationship.
To make this work with pyright, you'll need to use some technique other than dynamic ABC registration. A few options:
Change CloudPath and Path to actually use AnyPath as a base class. This requires that you are defining these classes, which is probably not true in this case.
Use a union type CloudPath | Path.
Use a constrained TypeVar that is constrained to either CloudPath or Path.
Use a Protocol class that describes the interface that is common to CloudPath and Path.
Can you explain why static type checkers will accept a list[str] as an argument to a parameter typed as accepting a typing.Sequence[str]? From what you explained it seems like this shouldn't work either unless something else is going on. I am wondering why I am not capable of recreating this behavior with my own custom virtual superclass.
This is a side effect of type stubs in typeshed where list is defined as a subclass of sequence. If you wanted to do same you have would need to have a stub file where you have a fake parent class hierarchy or use if TYPE_CHECKING. For pathlib Path this would require overriding typeshed stub for Path which is probably not advisable. 2/4 is solution I’d usually pick. 3 works although constrained type variables are strange to me.
Describe the bug
I am using
cloudpathlib
(the latest release,0.10.0
) in one of the repos I work in. It does some interesting stuff in regard to typing. It seems to be resulting in some undefined (?) behavior.They have an an abstract base class called
cloudpathlib.AnyPath
, which they register as a virtual super class ofcloudpathlib.CloudPath
andpathlib.Path
, except that they redefineAnyPath
's__new__
to returnUnion[CloudPath, Path]
.mypy seems to think that the returned instance is an
AnyPath
, while pylance seems to think the returned instance isUnion[CloudPath, Path]
.To Reproduce
Expected behavior
Even though the current implementation is kind of strange, I don't really expect pylance's message that
Cloudpath
is incompatible withAnyPath
sinceAnyPath
is technically a superclass ofPath
andCloudPath
... and I DO expect mypy's error message since typically virtual super classes define the methods that its virtual subclasses implement (whichAnyPath
does not).VS Code extension or command-line
The text was updated successfully, but these errors were encountered: