Are there any alternative to this overload case in python with typing?
Question:
currently I am implementing a lot of subclasses that should implement a function, this is a minimal example of the current project.
In this case, I have a function that needs to call, to the login of a user, but depending of the implementation injected previously the application will use UserUP
or UserToken
Because in login_user
I have all data available for the two options, I set the params like follow.
from typing import Protocol, runtime_checkable
@runtime_checkable
class User(Protocol):
def login(self, **kwargs) -> None:
raise NotImplementedError
class UserUP(User):
def login(self, user: str, password:str, **kwargs) -> None:
print(user)
print(password)
class UserToken(User):
def login(self, token:str, **kwargs) -> None:
print(token)
def login_user(user: User) -> None:
user.login(user="user", password="password", token="Token")
login_user(UserUP())
login_user(UserToken())
The problem is that when I run mypy
I get errors like the following:
app.py:10: error: Signature of "login" incompatible with supertype "User" [override]
app.py:10: note: Superclass:
app.py:10: note: def login(self, **kwargs: Any) -> None
app.py:10: note: Subclass:
app.py:10: note: def login(self, user: str, password: str, **kwargs: Any) -> None
app.py:16: error: Signature of "login" incompatible with supertype "User" [override]
app.py:16: note: Superclass:
app.py:16: note: def login(self, **kwargs: Any) -> None
app.py:16: note: Subclass:
app.py:16: note: def login(self, token: str, **kwargs: Any) -> None
Of course, the signature is incompatible, but which alternatives do I have to implement things like this?
Answers:
Use keyword_only marker in all signatures and describe all possible parameter in User.login
You need to expose which possible keywords can be used, and which type, in the main function.
from typing import Protocol, runtime_checkable
@runtime_checkable
class User(Protocol):
def login(self, *, user: str, password: str, token: str, **kwargs) -> None:
raise NotImplementedError
class UserUP(User):
def login(self, *, user: str, password: str, **kwargs) -> None:
print(user)
print(password)
class UserToken(User):
def login(self, *, token: str, **kwargs) -> None:
print(token)
def login_user(user: User) -> None:
user.login(user="user", password="password", token="Token")
login_user(UserUP())
login_user(UserToken())
Success: no issues found in 1 source file
currently I am implementing a lot of subclasses that should implement a function, this is a minimal example of the current project.
In this case, I have a function that needs to call, to the login of a user, but depending of the implementation injected previously the application will use UserUP
or UserToken
Because in login_user
I have all data available for the two options, I set the params like follow.
from typing import Protocol, runtime_checkable
@runtime_checkable
class User(Protocol):
def login(self, **kwargs) -> None:
raise NotImplementedError
class UserUP(User):
def login(self, user: str, password:str, **kwargs) -> None:
print(user)
print(password)
class UserToken(User):
def login(self, token:str, **kwargs) -> None:
print(token)
def login_user(user: User) -> None:
user.login(user="user", password="password", token="Token")
login_user(UserUP())
login_user(UserToken())
The problem is that when I run mypy
I get errors like the following:
app.py:10: error: Signature of "login" incompatible with supertype "User" [override]
app.py:10: note: Superclass:
app.py:10: note: def login(self, **kwargs: Any) -> None
app.py:10: note: Subclass:
app.py:10: note: def login(self, user: str, password: str, **kwargs: Any) -> None
app.py:16: error: Signature of "login" incompatible with supertype "User" [override]
app.py:16: note: Superclass:
app.py:16: note: def login(self, **kwargs: Any) -> None
app.py:16: note: Subclass:
app.py:16: note: def login(self, token: str, **kwargs: Any) -> None
Of course, the signature is incompatible, but which alternatives do I have to implement things like this?
Use keyword_only marker in all signatures and describe all possible parameter in User.login
You need to expose which possible keywords can be used, and which type, in the main function.
from typing import Protocol, runtime_checkable
@runtime_checkable
class User(Protocol):
def login(self, *, user: str, password: str, token: str, **kwargs) -> None:
raise NotImplementedError
class UserUP(User):
def login(self, *, user: str, password: str, **kwargs) -> None:
print(user)
print(password)
class UserToken(User):
def login(self, *, token: str, **kwargs) -> None:
print(token)
def login_user(user: User) -> None:
user.login(user="user", password="password", token="Token")
login_user(UserUP())
login_user(UserToken())
Success: no issues found in 1 source file