Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 14 additions & 12 deletions src/libsemigroups_pybind11/to.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
|libsemigroups_pybind11| objects from one type to another.
"""

from typing import _GenericAlias
from collections.abc import Iterator as _Iterator
from typing import Any as _Any, get_origin as _get_origin

from _libsemigroups_pybind11 import (
Order as _Order,
Expand Down Expand Up @@ -56,25 +57,26 @@
from .todd_coxeter import ToddCoxeter as _ToddCoxeter


# FIXME this function converts list[int] -> list, but shouldn't
def _nice_name(type_list):
"""Convert an iterable of type-like things into a string"""
single_element = False
if not isinstance(type_list, tuple):
single_element = True
type_list = [type_list]
def _nice_name(types: _Iterator[_Any]) -> str:
"""Convert an iterable of things into a string"""
not_tuple = False
if not isinstance(types, tuple):
not_tuple = True
types = (types,)
out = []
for t in type_list:
for t in types:
if isinstance(t, str):
out.append(t)
elif isinstance(t, _GenericAlias):
out.append(f'"{t}"')
elif _get_origin(t) is not None:
out.append(str(t))
elif hasattr(t, "__name__"):
out.append(t.__name__)
else:
out.append(str(t))
if single_element:
if not_tuple:
return out[0]
if len(types) == 1:
out[0] += ","
return f"({', '.join(out)})"


Expand Down
38 changes: 38 additions & 0 deletions tests/test_to.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

"""This module contains some tests for the to function."""

from typing import Literal

import pytest

# TODO(1) be good to remove the imports from _libsemigroups_pybind11, but
Expand Down Expand Up @@ -50,6 +52,7 @@
to,
)
from libsemigroups_pybind11.detail.cxx_wrapper import to_cxx
from libsemigroups_pybind11.to import _nice_name

###############################################################################
# Helper functions
Expand Down Expand Up @@ -1068,6 +1071,41 @@ def test_to_Congruence_010():
###############################################################################


@pytest.mark.parametrize(
"value, expected",
[
(list[int], "list[int]"),
(list[str], "list[str]"),
(dict[str, list[int]], "dict[str, list[int]]"),
(tuple[int, ...], "tuple[int, ...]"),
(Literal[1, 2], "typing.Literal[1, 2]"),
(list, "list"),
(str, "str"),
(Presentation, "Presentation"),
("Set", '"Set"'),
(Order.lenlex, "Order.lenlex"),
((Presentation,), "(Presentation,)"),
((Presentation, list[int]), "(Presentation, list[int])"),
(
(KnuthBendix, list[int], "Trie", Order.lenlex),
'(KnuthBendix, list[int], "Trie", Order.lenlex)',
),
],
)
def test_nice_name(value, expected):
assert _nice_name(value) == expected


def test_to_invalid_word_type():
with pytest.raises(TypeError) as exc_info:
to(sample_froidure_pin(), rtype=(Presentation, list[str]))

message = str(exc_info.value)
assert "\n * (Presentation, list[int])\n" in message
assert '\n * (KnuthBendix, list[int], "Trie", Order.lenlex)\n' in message
assert message.endswith("but found: (Presentation, list[str])")


def test_to_999():
x = 10
with pytest.raises(TypeError):
Expand Down
Loading