Description
Currently in typeshed, urllib.error.HTTPError is (accurately) annotated as inheriting both URLError
and urllib.response.addinfourl
. The addinfourl
class inherits addbase
, which is annotated as inheriting typing.BinaryIO. This appears to be an attempt to deal with the fact that addbase
actually inherits the (private) tempfile._TemporaryFileWrapper
, which is supposed to wrap a "file-like object", and proxies all attribute access to the wrapped object.
This makes some sense: BinaryIO
is supposed to be the typing "definition" of what "file-like object" means (at least in binary mode). And this works OK for type-checking code that accesses "file-like" methods on an HTTPError
instance. But it makes it impossible to actually instantiate an HTTPError
without a spurious mypy error, because the methods of typing.BinaryIO
(and its parent typing.IO
) are all decorated as @abstractmethod, and most of them are not overridden by the typeshed annotation of addbase
or addinfourl
.
So if you type-check this code (which works fine at runtime):
from io import StringIO
from urllib.error import HTTPError
http_error = HTTPError("", 500, "message", dict(), StringIO(''))
mypy gives you:
error: Cannot instantiate abstract class 'HTTPError' with abstract attributes '__enter__', '__exit__', ... and 'writelines' (16 methods suppressed)
I'm filing an issue rather than going straight to pull request because the correct fix here isn't obvious to me, and I'm hoping someone with more typeshed experience can offer a preferred solution. If so, I'm happy to implement it. The obvious solution seems to be repeating all the method definitions from typing.BinaryIO
and typing.IO
in the typeshed annotation for addbase
, without @abstractmethod
, but I'm hoping there might be an option that avoids this duplication.