1+ import numpy as np
2+
13from ctypes import byref , cast , c_char_p , c_ubyte , POINTER , sizeof
24from functools import wraps
3- from typing import Callable , Union
5+ from numpy .typing import DTypeLike
6+ from typing import Any , Callable , Iterable , Union
47
58from .errors import python_exception_to_igraph_error_t
9+ from .types import (
10+ np_type_of_igraph_bool_t ,
11+ np_type_of_igraph_real_t ,
12+ np_type_of_igraph_string ,
13+ )
614
715__all__ = ("bytes_to_str" , "get_raw_memory_view" , "nop" , "protect" , "protect_with" )
816
@@ -21,6 +29,57 @@ def bytes_to_str(
2129 return value .decode (encoding , errors )
2230
2331
32+ def get_numpy_attribute_type_from_iterable ( # noqa: C901
33+ it : Iterable [Any ],
34+ ) -> DTypeLike :
35+ """Determines the appropriate NumPy datatype to store all the items found in
36+ the given iterable as an attribute.
37+
38+ This means that this function basically classifies the iterable into one of
39+ the following data types:
40+
41+ - np_type_of_igraph_bool_t for Boolean attributes
42+ - np_type_of_igraph_real_t for numeric attributes
43+ - np_type_of_igraph_string for string attributes
44+ - np.object_ for any other (mixed) attribute type
45+
46+ When the iterable is empty, a numeric attribute will be assumed.
47+ """
48+ it = iter (it )
49+ try :
50+ item = next (it )
51+ except StopIteration :
52+ # Iterable empty
53+ return np_type_of_igraph_real_t
54+
55+ best_fit : DTypeLike
56+ if isinstance (item , bool ):
57+ best_fit = np_type_of_igraph_bool_t
58+ elif isinstance (item , (int , float , np .number )):
59+ best_fit = np_type_of_igraph_real_t
60+ elif isinstance (item , str ):
61+ best_fit = np_type_of_igraph_string
62+ else :
63+ return np .object_
64+
65+ for item in it :
66+ if isinstance (item , bool ):
67+ if best_fit == np_type_of_igraph_string :
68+ return np .object_
69+ elif isinstance (item , (int , float , np .number )):
70+ if best_fit == np_type_of_igraph_string :
71+ return np .object_
72+ else :
73+ best_fit = np_type_of_igraph_real_t
74+ elif isinstance (item , str ):
75+ if best_fit != np_type_of_igraph_string :
76+ return np .object_
77+ else :
78+ return np .object_
79+
80+ return best_fit
81+
82+
2483def get_raw_memory_view (obj ):
2584 """Returns a view into the raw bytes of a ctypes object."""
2685 return cast (byref (obj ), POINTER (c_ubyte * sizeof (obj ))).contents
0 commit comments