Source code for numpydantic.meta
"""
Metaprogramming functions for numpydantic to modify itself :)
"""
from pathlib import Path
from warnings import warn
from numpydantic.interface import Interface
_BUILTIN_IMPORTS = ("import typing", "import pathlib")
_PREAMBLE = """
# Add mypy-style generic params to a static type
# https://mypy.readthedocs.io/en/stable/generics.html#generic-type-aliases
TShape = typing.TypeVar('TShape')
TDtype = typing.TypeVar('TDtype')
"""
_STATIC_TYPES = ("TShape", "TDtype")
[docs]
def generate_ndarray_stub() -> str:
"""
Make a stub file based on the array interfaces that are available
"""
import_strings = []
type_names = [*_STATIC_TYPES]
for arr in Interface.input_types():
if arr.__module__ == "builtins":
continue
# Create import statements, saving aliased name of type if needed
if arr.__module__.startswith("numpydantic") or arr.__module__ == "typing":
type_name = str(arr) if arr.__module__ == "typing" else arr.__name__
if arr.__module__ != "typing":
import_strings.append(f"from {arr.__module__} import {type_name}")
else:
# since other packages could use the same name for an imported object
# (eg dask and zarr both use an Array class)
# we make an import alias from the module names to differentiate them
# in the type annotation
mod_name = "".join([a.capitalize() for a in arr.__module__.split(".")])
type_name = mod_name + arr.__name__
import_strings.append(
f"from {arr.__module__} import {arr.__name__} " f"as {type_name}"
)
type_names.append(type_name)
import_strings.extend(_BUILTIN_IMPORTS)
import_strings = list(dict.fromkeys(import_strings))
import_string = "\n".join(import_strings)
class_union = " | ".join(type_names)
ndarray_type = "NDArray = " + class_union
stub_string = "\n".join([import_string, _PREAMBLE, ndarray_type])
return stub_string
[docs]
def update_ndarray_stub() -> None:
"""
Update the ndarray.pyi string in the numpydantic file
"""
from numpydantic import ndarray
try:
stub_string = generate_ndarray_stub()
pyi_file = Path(ndarray.__file__).with_suffix(".pyi")
with open(pyi_file, "w") as pyi:
pyi.write(stub_string)
except Exception as e: # pragma: no cover
warn(
f"ndarray.pyi stub file could not be generated: {e}",
category=ImportWarning,
stacklevel=1,
)