-
Notifications
You must be signed in to change notification settings - Fork 234
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Annotate function which return a specific module (e.g. -> Literal[np]
)
#1039
Comments
I encountered a similar issue before. Although not with with the return type but rather version dependent imports, e.g. assign either Not sure if typing.TYPE_CHECKING:
import numpy as np
def load_numpy() -> types.ModuleType[np]:
... That's quite close to the how pyright already handles it at the moment. import numpy as np
reveal_type(np)
|
If possible, it's best to avoid dynamically loading modules and stick to the normal If you really need to describe a module as a type, one option is to use a protocol class to describe the interface provided by the module in question. PEP 544 specifically allows this. Pyright implements this functionality, but mypy hasn't yet implemented this. That's probably not what you're looking for in this case. As you pointed out, another option is to use an if TYPE_CHECKING:
import numpy as np
else
np = load_numpy() I don't think |
This quickly becomes unfeasible for larger namespaces though. The main numpy namespace for example contains ~550 objects; the duplicating necessary for defining all corresponding protocol method is massive and, at best, highly impractical. Secondly, as an additional data point: the same issue (no support for literal modules) was previously encountered in data-apis/array-api#267. |
It's not always possible, as pointed out in the use-cases. (e.g. NEP 37)
You solution load |
Any update on this issue ? Not being able to annotate module prevent to use auto-completion & type checking: def my_transformation(x, xnp: NpModule): # xnp can be jax.numpy, torch, tf.numpy
return xnp.sum(x) # << No auto-completion nor type-checking here |
You can be creative with the from typing import TYPE_CHECKING
if TYPE_CHECKING:
import numpy as lazymodule
else:
class lazymodule:
np = load_numpy()
@classmethod
def __getattr__(cls, attr):
return getattr(cls.np, attr)
reveal_type(lazymodule.array) |
Problem
Currently it's not possible to annotate a function which return a specific module, like:
-> types.ModuleType
does not work as too generic (no auto-complete, nor static type checking,...)Protocol
is not applicable in practice: maintaining a numpy protocol which has 500+ symbols is just not realisticUse case
Here are some concrete use-case where this feature is needed (also collected from this thread comments):
Numpy Enancement Propopsal 37 propose a recipe to have code working with various numpy implementation (
numpy
,jax.numpy
,tensorflow.numpy
):I developed my version at https://github.com/google/etils/tree/main/etils/enp#code-that-works-with-nparray-jnparray-tftensor
Lazy imports is a common pattern to only import a module if needed. Like: https://github.com/tensorflow/datasets/blob/76f8591def26afaca16340b06d057553582f6163/tensorflow_datasets/core/lazy_imports_lib.py#L40-L197
From another user comment: Similar issue to to 1. encountered at: __array_namespace__ type Hint data-apis/array-api#267
From another user comment:
Proposal
I would like to annotate my function as:
Or:
For the lazy-loading case,
typing.TYPE_CHECKING
pattern could be used:The text was updated successfully, but these errors were encountered: