Skip to content

Commit ecaad4f

Browse files
committed
refactor: AttributeValueList now uses a NumPy array as its backing store
1 parent 3a052c6 commit ecaad4f

File tree

9 files changed

+322
-230
lines changed

9 files changed

+322
-230
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from ..enums import AttributeType
2+
3+
__all__ = ("AttributeType",)
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import numpy as np
2+
3+
from numpy.typing import DTypeLike
4+
from typing import Any, Iterable
5+
6+
from .enums import AttributeType
7+
from ..types import (
8+
np_type_of_igraph_bool_t,
9+
np_type_of_igraph_real_t,
10+
)
11+
12+
__all__ = (
13+
"get_igraph_attribute_type_from_iterable",
14+
"get_numpy_attribute_type_from_iterable",
15+
"igraph_to_numpy_attribute_type",
16+
)
17+
18+
19+
def get_igraph_attribute_type_from_iterable( # noqa: C901
20+
it: Iterable[Any],
21+
) -> AttributeType:
22+
"""Determines the appropriate igraph attribute type to store all the items
23+
found in the given iterable as an attribute.
24+
25+
When the iterable is empty, the returned attribute type will be unspecified.
26+
"""
27+
it = iter(it)
28+
try:
29+
item = next(it)
30+
except StopIteration:
31+
# Iterable empty
32+
return AttributeType.UNSPECIFIED
33+
34+
best_fit: AttributeType
35+
if isinstance(item, bool):
36+
best_fit = AttributeType.BOOLEAN
37+
elif isinstance(item, (int, float, np.number)):
38+
best_fit = AttributeType.NUMERIC
39+
elif isinstance(item, str):
40+
best_fit = AttributeType.STRING
41+
else:
42+
return AttributeType.OBJECT
43+
44+
for item in it:
45+
if isinstance(item, bool):
46+
if best_fit == AttributeType.STRING:
47+
return AttributeType.OBJECT
48+
elif isinstance(item, (int, float, np.number)):
49+
if best_fit == AttributeType.STRING:
50+
return AttributeType.OBJECT
51+
else:
52+
best_fit = AttributeType.NUMERIC
53+
elif isinstance(item, str):
54+
if best_fit != AttributeType.STRING:
55+
return AttributeType.OBJECT
56+
else:
57+
return AttributeType.OBJECT
58+
59+
return best_fit
60+
61+
62+
def get_numpy_attribute_type_from_iterable(
63+
it: Iterable[Any],
64+
) -> DTypeLike:
65+
"""Determines the appropriate NumPy attribute type to store all the items
66+
found in the given iterable as an attribute.
67+
68+
This is done by first determining the corresponding igraph attribute type,
69+
and mapping that type to a NumPy type.
70+
71+
When the iterable is empty, a numeric attribute will be assumed.
72+
"""
73+
attr_type = get_igraph_attribute_type_from_iterable(it)
74+
if attr_type is AttributeType.UNSPECIFIED:
75+
attr_type = AttributeType.NUMERIC
76+
return igraph_to_numpy_attribute_type(attr_type)
77+
78+
79+
def igraph_to_numpy_attribute_type(type: AttributeType) -> DTypeLike:
80+
"""Converts an igraph attribute type to an equivalent NumPy data type."""
81+
if type is AttributeType.BOOLEAN:
82+
return np_type_of_igraph_bool_t
83+
elif type is AttributeType.NUMERIC:
84+
return np_type_of_igraph_real_t
85+
else:
86+
return np.object_

0 commit comments

Comments
 (0)