ValvePython / steam

☁️ Python package for interacting with Steam
http://steam.readthedocs.io
MIT License
1.06k stars 129 forks source link

Add type annotations #377

Open rpdelaney opened 2 years ago

rpdelaney commented 2 years ago

Is your feature request related to a problem? Please describe.

Consider this class:

from steam.steamid import SteamID

from typing import Generator, List, Tuple, Union

bans: List[str] = []

class Player:
    def __init__(self, name: str, steamid_64: str) -> None:
        self.name = name
        self.steamid_64 = steamid_64

    @property
    def steamid(self) -> str:
        try:
            return SteamID(self.steamid_64).as_steam2
        except ValueError:
            return ""

    @property
    def valid_steamid(self) -> bool:
        try:
            return SteamID.is_valid(SteamID(self.steamid_64))
        except ValueError:
            return False

    @property
    def is_banned(self) -> bool:
        return self.steamid in bans

    @property
    def url(self) -> str:
        try:
            return SteamID(self.steamid_64).community_url
        except ValueError:
            return ""

    def __iter__(self) -> Generator[Tuple[str, Union[int, str]], None, None]:
        yield "name", self.name
        yield "steamid64", self.steamid_64
        yield "steamid", self.steamid
        yield "valid_steamid", self.valid_steamid
        yield "is_banned", self.is_banned
        yield "url", self.url

Because the instance methods in the steam module are untyped, mypy gives errors:

foo.py:16:13: error: Returning Any from function declared to return "str"  [no-any-return]
foo.py:23:13: error: Returning Any from function declared to return "bool"  [no-any-return]
foo.py:34:13: error: Returning Any from function declared to return "str"  [no-any-return]
Found 3 errors in 1 file (checked 1 source file)

To silence the warnings, I must coerce the returned expressions:

diff --git i/foo.py w/foo.py
index f1f6722..d15cbb6 100644
--- i/foo.py
+++ w/foo.py
@@ -13,14 +13,14 @@ class Player:
     @property
     def steamid(self) -> str:
         try:
-            return SteamID(self.steamid_64).as_steam2
+            return str(SteamID(self.steamid_64).as_steam2)
         except ValueError:
             return ""

     @property
     def valid_steamid(self) -> bool:
         try:
-            return SteamID.is_valid(SteamID(self.steamid_64))
+            return bool(SteamID.is_valid(SteamID(self.steamid_64)))
         except ValueError:
             return False

@@ -31,7 +31,7 @@ class Player:
     @property
     def url(self) -> str:
         try:
-            return SteamID(self.steamid_64).community_url
+            return str(SteamID(self.steamid_64).community_url)
         except ValueError:
             return ""

Describe the solution you'd like

This would aid consumers in type checking their code that depends on steam.

That would guard against returning wrong types as the module develops.

Describe alternatives you've considered

The easiest option. It's not so inconvenient to coerce or annotate types in my code. But the tools are available in python, and I think it's worth considering.

Thanks for reading. Happy to answer questions.

Gobot1234 commented 2 years ago

This is being worked on (see #286) but it will have to wait until V3 as Python 2 support won't be dropped until then.