Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python library: optionally support numpy types without depending on numpy

Tags:

python

numpy

Context

We develop a Python library that contains a function expecting a numlike parameter. We specify this in our signature and make use of python type hints:

def cool(value: float | int | List[float | int]) 

🏳 Problem & Goal

During runtime, we noticed it's fine to pass in numpy number types as well, e.g. np.float16(1.2345). So we thought: why not incorporate "numpy number types" into our signature as this would be beneficial for the community that will use our library.

However, we don't want numpy as dependency in our project. We'd like to only signify in the method signature that we can take a float, int, a list of them OR any "numpy number type". If the user hasn't installed numpy on their system, they should still be able to use our library and just ignore that they could possibly pass in a "numpy number type" as well.

We don't want to depend on numpy as we don't use it in our library (except for allowing their types in our method signature). So why include it in our dependency graph? There's no reason to do so. One dependency less is better.

Additional requirements/context

  • We search for an answer that is compatible with all Python versions >=3.8.
  • (The answer should work with setuptools>=69.0.)
  • The answer should be such that we get proper IntelliSense (Ctrl + Space) when typing cool( in an IDE, e.g. VSCode.
  • This is what our pyproject.toml looks like.

Efforts

  • We've noticed the option [project.optional-dependencies] for the pyproject.toml file, see here. However, it remains unclear how this optional dependencies declaration helps us in providing optional numpy datatypes in our method signatures.
  • numpy provides the numpy.typing type annotations. Is it somehow possible to only depend on this subpackage?
  • We did search on search engines and found this SO question, however our question is more specific with regards to how we can only use types from another module. We also found this SO question, but despite having "optional" in its title, it's not about optional numpy types.
like image 794
Splines Avatar asked Aug 13 '26 05:08

Splines


1 Answers

Defer evaluation of annotations, and only import numpy conditionally.

from __future__ import annotations
import typing as t

if t.TYPE_CHECKING:
    import numpy as np

def cool(value: int | np.floating | etc ...):
    ...

Now the numpy dependency is only necessary when type-checking.

See PEP 563 – Postponed Evaluation of Annotations

Side-questions..

numpy provides the numpy.typing type annotations. Is it somehow possible to only depend on this subpackage?

No, this is not possible.

We've noticed the option [project.optional-dependencies] for the pyproject.toml file ...

It doesn't really help you much here. It could still be useful if you wanted "extra" dependencies which the user can opt-in for, e.g.:

pip install mypkg          # install with required dependencies
pip install mypkg[typing]  # install with extra dependencies such as numpy

Then you could use this to easily install the package along with the soft-deps in your CI, for example.

like image 71
wim Avatar answered Aug 16 '26 15:08

wim



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!