Skip to content

Commit 4b33f39

Browse files
committed
feat: strerror() works now
1 parent 38a50ab commit 4b33f39

File tree

6 files changed

+49
-18
lines changed

6 files changed

+49
-18
lines changed

src/codegen/types.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
ERROR:
2+
PY_TYPE: int
23
CTYPES_RETURN_TYPE: handle_igraph_error_t
34

45
BOOLEAN:
@@ -32,7 +33,7 @@ CSTRING:
3233
INCONV:
3334
IN: '%C% = %I%.encode("utf-8")'
3435
OUT: "%C% = c_char_p()"
35-
OUTCONV: '%I% = %C%.value.decode("utf-8", "replace")'
36+
OUTCONV: "%I% = bytes_to_str(%C%)"
3637

3738
VECTOR:
3839
PY_TYPE: Iterable[float]

src/igraph_ctypes/_internal/conversion.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
VertexPair,
5959
VertexSelector,
6060
)
61+
from .utils import bytes_to_str
6162
from .wrappers import (
6263
_EdgeSelector,
6364
_Graph,
@@ -71,6 +72,7 @@
7172

7273
__all__ = (
7374
"any_to_igraph_bool_t",
75+
"bytes_to_str",
7476
"edgelike_to_igraph_integer_t",
7577
"edge_capacities_to_igraph_vector_t",
7678
"edge_capacities_to_igraph_vector_t_view",
@@ -109,11 +111,6 @@
109111
)
110112

111113

112-
################################################################################
113-
# Conversion from Python data types to igraph #
114-
################################################################################
115-
116-
117114
def any_to_igraph_bool_t(obj: Any) -> igraph_bool_t:
118115
"""Converts an arbitrary Python object to an igraph boolean by taking its
119116
truth value.

src/igraph_ctypes/_internal/functions.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -99,16 +99,16 @@ def delete_vertices(graph: _Graph, vertices: VertexSelector) -> None:
9999
igraph_delete_vertices(c_graph, c_vertices.unwrap())
100100

101101

102-
def delete_vertices_idx(graph: _Graph, vertices: VertexSelector) -> Tuple[npt.NDArray[np_type_of_igraph_integer_t], npt.NDArray[np_type_of_igraph_integer_t]]:
103-
"""Type-annotated wrapper for ``igraph_delete_vertices_idx``."""
102+
def delete_vertices_map(graph: _Graph, vertices: VertexSelector) -> Tuple[npt.NDArray[np_type_of_igraph_integer_t], npt.NDArray[np_type_of_igraph_integer_t]]:
103+
"""Type-annotated wrapper for ``igraph_delete_vertices_map``."""
104104
# Prepare input arguments
105105
c_graph = graph
106106
c_vertices = vertex_selector_to_igraph_vs_t(vertices, graph)
107107
c_idx = _VectorInt.create(0)
108108
c_invidx = _VectorInt.create(0)
109109

110110
# Call wrapped function
111-
igraph_delete_vertices_idx(c_graph, c_vertices.unwrap(), c_idx, c_invidx)
111+
igraph_delete_vertices_map(c_graph, c_vertices.unwrap(), c_idx, c_invidx)
112112

113113
# Prepare output arguments
114114
idx = igraph_vector_int_t_to_numpy_array(c_idx)
@@ -1696,17 +1696,18 @@ def distances_bellman_ford(graph: _Graph, weights: Iterable[float], from_: Verte
16961696
return res
16971697

16981698

1699-
def distances_johnson(graph: _Graph, weights: Iterable[float], from_: VertexSelector = "all", to: VertexSelector = "all") -> npt.NDArray[np_type_of_igraph_real_t]:
1699+
def distances_johnson(graph: _Graph, from_: VertexSelector = "all", to: VertexSelector = "all", weights: Optional[Iterable[float]] = None, mode: NeighborMode = NeighborMode.OUT) -> npt.NDArray[np_type_of_igraph_real_t]:
17001700
"""Type-annotated wrapper for ``igraph_distances_johnson``."""
17011701
# Prepare input arguments
17021702
c_graph = graph
17031703
c_res = _Matrix.create(0)
17041704
c_from = vertex_selector_to_igraph_vs_t(from_, graph)
17051705
c_to = vertex_selector_to_igraph_vs_t(to, graph)
17061706
c_weights = edge_weights_to_igraph_vector_t_view(weights, graph)
1707+
c_mode = c_int(mode)
17071708

17081709
# Call wrapped function
1709-
igraph_distances_johnson(c_graph, c_res, c_from.unwrap(), c_to.unwrap(), c_weights)
1710+
igraph_distances_johnson(c_graph, c_res, c_from.unwrap(), c_to.unwrap(), c_weights, c_mode)
17101711

17111712
# Prepare output arguments
17121713
res = igraph_matrix_t_to_numpy_array(c_res)
@@ -5942,7 +5943,20 @@ def has_attribute_table() -> bool:
59425943

59435944
# igraph_status: no Python type known for type: EXTRA
59445945

5945-
# igraph_strerror: no Python type known for type: ERROR
5946+
5947+
def strerror(igraph_errno: int) -> str:
5948+
"""Type-annotated wrapper for ``igraph_strerror``."""
5949+
# Prepare input arguments
5950+
c_igraph_errno = igraph_errno
5951+
5952+
# Call wrapped function
5953+
c__result = igraph_strerror(c_igraph_errno)
5954+
5955+
# Prepare return value
5956+
py__result = bytes_to_str(c__result)
5957+
5958+
# Construct return value
5959+
return py__result
59465960

59475961

59485962
def expand_path_to_pairs(path: Iterable[VertexLike]) -> None:
@@ -5997,7 +6011,7 @@ def version() -> Tuple[str, int, int, int]:
59976011
igraph_version(c_version_string, c_major, c_minor, c_subminor)
59986012

59996013
# Prepare output arguments
6000-
version_string = c_version_string.value.decode("utf-8", "replace")
6014+
version_string = bytes_to_str(c_version_string)
60016015
major = c_major.value
60026016
minor = c_minor.value
60036017
subminor = c_subminor.value

src/igraph_ctypes/_internal/lib.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -392,9 +392,9 @@ def _load_igraph_c_library():
392392
igraph_delete_vertices.restype = handle_igraph_error_t
393393
igraph_delete_vertices.argtypes = [POINTER(igraph_t), igraph_vs_t]
394394

395-
igraph_delete_vertices_idx = _lib.igraph_delete_vertices_idx
396-
igraph_delete_vertices_idx.restype = handle_igraph_error_t
397-
igraph_delete_vertices_idx.argtypes = [POINTER(igraph_t), igraph_vs_t, POINTER(igraph_vector_int_t), POINTER(igraph_vector_int_t)]
395+
igraph_delete_vertices_map = _lib.igraph_delete_vertices_map
396+
igraph_delete_vertices_map.restype = handle_igraph_error_t
397+
igraph_delete_vertices_map.argtypes = [POINTER(igraph_t), igraph_vs_t, POINTER(igraph_vector_int_t), POINTER(igraph_vector_int_t)]
398398

399399
igraph_vcount = _lib.igraph_vcount
400400
igraph_vcount.restype = igraph_integer_t
@@ -774,7 +774,7 @@ def _load_igraph_c_library():
774774

775775
igraph_distances_johnson = _lib.igraph_distances_johnson
776776
igraph_distances_johnson.restype = handle_igraph_error_t
777-
igraph_distances_johnson.argtypes = [POINTER(igraph_t), POINTER(igraph_matrix_t), igraph_vs_t, igraph_vs_t, POINTER(igraph_vector_t)]
777+
igraph_distances_johnson.argtypes = [POINTER(igraph_t), POINTER(igraph_matrix_t), igraph_vs_t, igraph_vs_t, POINTER(igraph_vector_t), igraph_neimode_t]
778778

779779
igraph_distances_floyd_warshall = _lib.igraph_distances_floyd_warshall
780780
igraph_distances_floyd_warshall.restype = handle_igraph_error_t
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from ctypes import c_char_p
2+
3+
4+
def bytes_to_str(value: bytes, encoding: str = "utf-8", errors: str = "replace") -> str:
5+
"""Converts a C string represented as a Python bytes object or as a
6+
ctypes ``c_char_p`` object into a Python string, using the given encoding
7+
and error handling.
8+
"""
9+
if isinstance(value, c_char_p):
10+
wrapped = value.value
11+
return wrapped.decode(encoding, errors) if wrapped is not None else ""
12+
else:
13+
return value.decode(encoding, errors)

test/test_misc.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
from igraph_ctypes._internal.functions import version
1+
from igraph_ctypes._internal.functions import strerror, version
2+
3+
4+
def test_strerror():
5+
assert strerror(0) == "No error"
6+
assert strerror(1) == "Failed"
7+
assert strerror(9) == "Invalid mode"
28

39

410
def test_version():

0 commit comments

Comments
 (0)