al45tair/netifaces

Provide *.pyi stubs for mypy

Opened this issue · 9 comments

jolaf commented

Didn't you think of providing static typing stubs for this library?

jolaf commented

For the existing API it should be rather simple, like this:

# Stubs for netifaces (Python 3)

from typing import Any, Mapping, Sequence, Tuple, Union

AF_APPLETALK: int
AF_ASH: int
AF_ATMPVC: int
AF_ATMSVC: int
AF_AX25: int
AF_BLUETOOTH: int
AF_BRIDGE: int
AF_DECnet: int
AF_ECONET: int
AF_FILE: int
AF_INET: int
AF_INET6: int
AF_IPX: int
AF_IRDA: int
AF_ISDN: int
AF_KEY: int
AF_LINK: int
AF_NETBEUI: int
AF_NETLINK: int
AF_NETROM: int
AF_PACKET: int
AF_PPPOX: int
AF_ROSE: int
AF_ROUTE: int
AF_SECURITY: int
AF_SNA: int
AF_UNIX: int
AF_UNSPEC: int
AF_WANPIPE: int
AF_X25: int

address_families: Mapping[int, str]

version: str

def interfaces() -> Sequence[str]: ...

def ifaddresses(interface: str) -> Mapping[int, Sequence[Mapping[str, str]]]: ...

def gateways() -> Mapping[Union[int, str], Union[Sequence[Tuple[str, str, bool]], Mapping[int, Tuple[str, str]]]]: ...
jolaf commented

This stub could be added as __init__.pyi to the library package together with the netifaces.*.so file and empty py.typed file to mark the package as static-typed (per PEP 561).

jolaf commented

The alternative would be to donate this stub file to python/typeshed.
I could do it if you approve.

jolaf commented

Hello? :)

Sorry, I've been quite busy with other things (not least my personal life, which has all fallen apart).

I don't think it's quite as simple as you make out; the address family constants don't necessarily exist (which do depends on the platform you're on), and having not read PEP 561 (yet) I don't know whether declaring their types if they aren't actually in existence is allowable.

(As for your first comment, no, I didn't, because I hadn't seen PEP 561, which netifaces predates.)

jolaf commented

My condolences. Shit happens, indeed.

Static typing is for checking the code is okay, not for guaranteeing it would work correctly.
So it's better to have unavailable constants defined in stubs, than having available ones undefined in stubs.

Also, the general typeshed rule is better having incomplete or non-perfect stubs than no stubs at all.

The stubs can use traditional methods like if sys.platform == 'win32': to filter platform-dependent things, but what if I develop a code that would run in multiple platforms, and I have those "ifs" in my code itself, and I want to use the respective constants in corresponding branches? It would mean I would have mypy complain on whatever platform I use.

So my suggestion is to have all possible constants listed in the stub and just ignore the fact some of them may be unavailable on some platforms.

Or, it may be worth add comments to particular constants like "Available on Linux" or "Unavailable on Linux", that would help the future developers understand, why mypy is ok with that constant, but runtime is not.

jolaf commented

For example, see typeshed/blob/master/stdlib/3/os/__init__.pyi
using if sys.platform != 'win32' for a similar purpose.

@jolaf Slightly OT, would you mind if I included the stub you provided here in ifaddr? I'm considering implementing a netifaces-emulation layer and adding type hints to the project, so it'd naturally fit there (with you as the author).

jolaf commented

@jstasiak Sure no problem.