`__package__` in the global namespace should have type `str`, not `str | None`
Question
I am unsure about the following, but mypy doesn't detect it:
$ ty check t.py
t.py:4:23: error[invalid-argument-type] Argument to function `version` is incorrect: Expected `str`, found `str | None`
$ cat t.py
from importlib.metadata import version
__version__ = version(__package__)
Version
0.0.3
fixing it will cause a mypy issue:
__version__ = version(cast('str', __package__)) # E: Redundant cast to "str" [redundant-cast]
fixing it will cause a
mypyissue:
__version__ = version(cast('str', __package__)) # E: Redundant cast to "str" [redundant-cast]
A solution to keep mypy etc happy would be to narrow out the | None for ty instead of cast
from importlib.metadata import version
__version__ = version(__package__ or "unset")
# or
if __package__:
__version__ = version(__package__)
else:
__version__ = version("unset")
https://play.ty.dev/edb7161a-2b3d-4373-87ed-c4f60edf5bfc
I think this is similar to: https://github.com/astral-sh/ty/issues/860 where based on typeshed alone __package__ can be None https://github.com/search?q=repo%3Apython%2Ftypeshed%20__package__&type=code but typecheckers can probably infer that at runtime it will only be str
Thanks! This issue is similar to https://github.com/astral-sh/ty/issues/860.
We get our type here from typeshed's types.ModuleType stub: https://github.com/python/typeshed/blob/8d96801533918957fb194e101cb321bfe1f836f8/stdlib/types.pyi#L362-L368. The reason why typeshed has the type str | None for this attribute is this line in the Python data model:
defaults to
Nonefor modules created dynamically using the types.ModuleType constructor; use importlib.util.module_from_spec() instead to ensure the attribute is set to a str.
But when we encounter __package__ in the global namespace like this, it's extremely likely that the module is going to be implicitly created by the Python interpreter rather than created using an explicit types.ModuleType instantiation. So I think we could safely override typeshed's type here and infer str for __package__ in the global namespace.