mrd-python 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
mrd/_dtypes.py ADDED
@@ -0,0 +1,89 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
3
+
4
+ import datetime
5
+ from types import GenericAlias
6
+ import sys
7
+
8
+ if sys.version_info >= (3, 10):
9
+ from types import UnionType
10
+
11
+ from typing import Any, Callable, Union, cast, get_args, get_origin
12
+ import numpy as np
13
+ from . import yardl_types as yardl
14
+
15
+
16
+ def make_get_dtype_func(
17
+ dtype_map: dict[
18
+ Union[type, GenericAlias],
19
+ Union[np.dtype[Any], Callable[[tuple[type, ...]], np.dtype[Any]]],
20
+ ]
21
+ ) -> Callable[[Union[type, GenericAlias]], np.dtype[Any]]:
22
+ dtype_map[bool] = np.dtype(np.bool_)
23
+ dtype_map[yardl.Int8] = np.dtype(np.int8)
24
+ dtype_map[yardl.UInt8] = np.dtype(np.uint8)
25
+ dtype_map[yardl.Int16] = np.dtype(np.int16)
26
+ dtype_map[yardl.UInt16] = np.dtype(np.uint16)
27
+ dtype_map[yardl.Int32] = np.dtype(np.int32)
28
+ dtype_map[yardl.UInt32] = np.dtype(np.uint32)
29
+ dtype_map[yardl.Int64] = np.dtype(np.int64)
30
+ dtype_map[yardl.UInt64] = np.dtype(np.uint64)
31
+ dtype_map[yardl.Size] = np.dtype(np.uint64)
32
+ dtype_map[yardl.Float32] = np.dtype(np.float32)
33
+ dtype_map[yardl.Float64] = np.dtype(np.float64)
34
+ dtype_map[yardl.ComplexFloat] = np.dtype(np.complex64)
35
+ dtype_map[yardl.ComplexDouble] = np.dtype(np.complex128)
36
+ dtype_map[datetime.date] = np.dtype("datetime64[D]")
37
+ dtype_map[yardl.Time] = np.dtype("timedelta64[ns]")
38
+ dtype_map[yardl.DateTime] = np.dtype("datetime64[ns]")
39
+ dtype_map[str] = np.dtype(np.object_)
40
+
41
+ # Add the Python types to the dictionary too, but these may not be
42
+ # correct since they map to several dtypes
43
+ dtype_map[int] = np.dtype(np.int64)
44
+ dtype_map[float] = np.dtype(np.float64)
45
+ dtype_map[complex] = np.dtype(np.complex128)
46
+
47
+ dtype_map[list] = lambda type_args: np.dtype(np.object_)
48
+ dtype_map[dict] = lambda type_args: np.dtype(np.object_)
49
+ dtype_map[np.ndarray] = lambda type_args: np.dtype(np.object_) # type: ignore
50
+
51
+ def get_dtype_impl(
52
+ dtype_map: dict[
53
+ Union[type, GenericAlias],
54
+ Union[np.dtype[Any], Callable[[tuple[type, ...]], np.dtype[Any]]],
55
+ ],
56
+ t: Union[type, GenericAlias],
57
+ ) -> np.dtype[Any]:
58
+ # Check dtype map for this type first
59
+ if (res := dtype_map.get(t, None)) is not None:
60
+ if callable(res):
61
+ raise RuntimeError(f"Generic type arguments not provided for {t}")
62
+ else:
63
+ return res
64
+
65
+ origin = get_origin(t)
66
+
67
+ if origin == Union or (
68
+ sys.version_info >= (3, 10) and isinstance(t, UnionType)
69
+ ):
70
+ return _get_union_dtype(get_args(t))
71
+
72
+ # Here, t is either invalid (no dtype registered)
73
+ # or t is a types.GenericAlias with type arguments specified
74
+ if origin is not None and (res := dtype_map.get(origin, None)) is not None:
75
+ if callable(res):
76
+ return res(get_args(t))
77
+
78
+ raise RuntimeError(f"Cannot find dtype for {t}")
79
+
80
+ def _get_union_dtype(args: tuple[type, ...]) -> np.dtype[Any]:
81
+ if len(args) == 2 and args[1] == cast(type, type(None)):
82
+ # This is an optional type
83
+ inner_type = get_dtype_impl(dtype_map, args[0])
84
+ return np.dtype(
85
+ [("has_value", np.bool_), ("value", inner_type)], align=True
86
+ )
87
+ return np.dtype(np.object_)
88
+
89
+ return lambda t: get_dtype_impl(dtype_map, t)