diff --git a/docs/source/data-structures/presentations/to-inverse-present.rst b/docs/source/data-structures/presentations/to-inverse-present.rst index d8a5a6ed..148b7f59 100644 --- a/docs/source/data-structures/presentations/to-inverse-present.rst +++ b/docs/source/data-structures/presentations/to-inverse-present.rst @@ -43,7 +43,7 @@ the following values for *args*: Additionally, specify the following for *Return*: - - ``InversePresentation`` for constructing an :any:`InversePresentation` + - ``(InversePresentation,)`` for constructing an :any:`InversePresentation` over words of the same type as those in *p*. This function returns an :any:`InversePresentation` with rules equivalent to @@ -73,7 +73,7 @@ This function throws a :any:`LibsemigroupsError` if >>> presentation.add_rule(p, 'aaa', 'b') >>> presentation.add_rule(p, 'bac', 'cab') - >>> ip = to(p, Return=InversePresentation) + >>> ip = to(p, Return=(InversePresentation,)) >>> ip.alphabet() 'abcdef' >>> ip.inverses() diff --git a/docs/source/data-structures/presentations/to-present.rst b/docs/source/data-structures/presentations/to-present.rst index 5d4d923b..740d1e3d 100644 --- a/docs/source/data-structures/presentations/to-present.rst +++ b/docs/source/data-structures/presentations/to-present.rst @@ -167,10 +167,14 @@ following values for *args*: - **kb** (:any:`KnuthBendix`) -- the :any:`KnuthBendix` from which to obtain the rules. -Additionally, specify the following for *Return*: +Additionally, specify one of the following for *Return*: - - ``Presentation`` for constructing a :any:`Presentation` over words of the - same type as that in *kb*. + - ``(Presentation,)`` for constructing a :any:`Presentation` over words of + the same type as that in *kb*. + - ``(Presentation, str)`` for constructing a :any:`Presentation` over words + of type ``str``. + - ``(Presentation, List[int]`` for constructing a :any:`Presentation` over + words of type ``List[int]``. This function constructs and returns a :any:`Presentation` object using the currently active rules of *kb*. @@ -203,7 +207,7 @@ enumerates *kb*) prior to calling this function. >>> kb = KnuthBendix(congruence_kind.twosided, p1) >>> kb.run() - >>> p2 = to(kb, Return=Presentation) + >>> p2 = to(kb, Return=(Presentation,)) >>> for p in [p1, p2]: ... presentation.sort_each_rule(p) ... presentation.sort_rules(p) diff --git a/docs/source/data-structures/to-function.rst b/docs/source/data-structures/to-function.rst index 313b20c7..e9136cd9 100644 --- a/docs/source/data-structures/to-function.rst +++ b/docs/source/data-structures/to-function.rst @@ -16,10 +16,10 @@ to another type. These mostly only apply to the types implementing the main algorithms in ``libsemigroups_pybind11``. For example, to convert a :any:`ToddCoxeter` ``tc`` object to a -:any:`FroidurePin` object, you can simply do ``to(tc, Return=FroidurePin)``. +:any:`FroidurePin` object, you can simply do ``to(tc, Return=(FroidurePin,))``. A summary of the possible conversions available in ``libsemigroups_pybind11`` of -``to(FromType, Return=ToType)`` are given below, where the rows correspond to +``to(FromType, Return=(ToType,))`` are given below, where the rows correspond to ``ToType`` and the columns to ``FromType``: .. image:: ../../pictures/to-table.svg diff --git a/docs/source/main-algorithms/froidure-pin/to-froidure-pin.rst b/docs/source/main-algorithms/froidure-pin/to-froidure-pin.rst index 6ea9b71f..1f9dd3d2 100644 --- a/docs/source/main-algorithms/froidure-pin/to-froidure-pin.rst +++ b/docs/source/main-algorithms/froidure-pin/to-froidure-pin.rst @@ -46,7 +46,7 @@ following values for *args*: Additionally, specify the following for *Return*: - - ``FroidurePin`` for constructing a :any:`FroidurePin`. + - ``(FroidurePin,)`` for constructing a :any:`FroidurePin`. The :any:`FroidurePin` object returned is isomorphic to the quotient of the underlying semigroup or monoid of *cong* by the congruence represented by @@ -72,7 +72,7 @@ This function throws a :any:`LibsemigroupsError` if ``cong.kind`` is not >>> presentation.add_rule(p, [1, 1], [1]) >>> cong = Congruence(congruence_kind.twosided, p) - >>> fp = to(cong, Return=FroidurePin) + >>> fp = to(cong, Return=(FroidurePin,)) >>> fp.run() >>> fp.size() == cong.number_of_classes() @@ -90,7 +90,7 @@ values for *args*: Additionally, specify the following for *Return*: - - ``FroidurePin`` for constructing a :any:`FroidurePin`. + - ``(FroidurePin,)`` for constructing a :any:`FroidurePin`. The :any:`FroidurePin` object returned is isomorphic to the quotient semigroup or monoid represented by *k*. @@ -121,7 +121,7 @@ This function throws a :any:`LibsemigroupsError` if the >>> presentation.add_rule(p, 'ef', 'dg') >>> k = Kambites(congruence_kind.twosided, p) - >>> fp = to(k, Return=FroidurePin) + >>> fp = to(k, Return=(FroidurePin,)) >>> fp.enumerate(100) >>> fp.current_size() == 8205 @@ -140,7 +140,7 @@ following values for *args*: Additionally, specify the following for *Return*: - - ``FroidurePin`` for constructing a :any:`FroidurePin`. + - ``(FroidurePin,)`` for constructing a :any:`FroidurePin`. The :any:`FroidurePin` object returned is isomorphic to the quotient semigroup or monoid represented by *kb*. @@ -165,7 +165,7 @@ This function throws a :any:`LibsemigroupsError` if ``kb.kind()`` is not >>> presentation.add_rule(p, [1, 1], [1]) >>> kb = KnuthBendix(congruence_kind.twosided, p) - >>> fp = to(kb, Return=FroidurePin) + >>> fp = to(kb, Return=(FroidurePin,)) >>> fp.run() >>> fp.size() == kb.number_of_classes() @@ -184,7 +184,7 @@ following values for *args*: Additionally, specify the following for *Return*: - - ``FroidurePin`` for constructing a :any:`FroidurePin`. + - ``(FroidurePin,)`` for constructing a :any:`FroidurePin`. The :any:`FroidurePin` object returned is isomorphic to the quotient semigroup or monoid represented by *tc*. @@ -209,7 +209,7 @@ This function throws a :any:`LibsemigroupsError` if ``tc.kind()`` is not >>> presentation.add_rule(p, [1, 1], [1]) >>> tc = ToddCoxeter(congruence_kind.twosided, p) - >>> fp = to(tc, Return=FroidurePin) + >>> fp = to(tc, Return=(FroidurePin,)) >>> fp.run() >>> fp.size() == tc.number_of_classes() @@ -237,7 +237,7 @@ or Additionally, specify the following for *Return*: - - ``FroidurePin`` for constructing a :any:`FroidurePin`. + - ``(FroidurePin,)`` for constructing a :any:`FroidurePin`. Each label ``n`` in the :any:`WordGraph` will correspond to a generator ``f`` in the output :any:`FroidurePin` such that ``f[s] = t`` whenever there is an edge @@ -286,7 +286,7 @@ corresponding :math:`f`. ... w, # wg ... 1, # first ... 2, # last - ... Return=FroidurePin + ... Return=(FroidurePin,) ... ) >>> fp.run() diff --git a/docs/source/main-algorithms/knuth-bendix/to-knuth-bendix.rst b/docs/source/main-algorithms/knuth-bendix/to-knuth-bendix.rst index 149dde76..f19248fd 100644 --- a/docs/source/main-algorithms/knuth-bendix/to-knuth-bendix.rst +++ b/docs/source/main-algorithms/knuth-bendix/to-knuth-bendix.rst @@ -46,7 +46,7 @@ rewriter, specify all of the following values for *args*: Additionally, specify the following for *Return*: - - ``KnuthBendix`` for constructing a :any:`KnuthBendix` with the default + - ``(KnuthBendix,)`` for constructing a :any:`KnuthBendix` with the default rewriter. This function converts a :any:`ToddCoxeter` object *tc* to a :any:`KnuthBendix` @@ -77,7 +77,7 @@ the semigroup defined by *tc*. >>> kb = to( ... congruence_kind.twosided, # knd ... tc, # tc - ... Return=KnuthBendix + ... Return=(KnuthBendix,) ... ) >>> kb.run() diff --git a/docs/source/main-algorithms/todd-coxeter/to-todd-coxeter.rst b/docs/source/main-algorithms/todd-coxeter/to-todd-coxeter.rst index ac696ebf..dd9c64b9 100644 --- a/docs/source/main-algorithms/todd-coxeter/to-todd-coxeter.rst +++ b/docs/source/main-algorithms/todd-coxeter/to-todd-coxeter.rst @@ -105,7 +105,7 @@ following values for *args*: Additionally, specify the following for *Return*: - - ``ToddCoxeter`` for constructing a :any:`ToddCoxeter`. + - ``(ToddCoxeter,)`` for constructing a :any:`ToddCoxeter`. This function converts the :any:`KnuthBendix` object *kb* into a :any:`ToddCoxeter` object using the right Cayley graph of the semigroup @@ -141,7 +141,7 @@ This will throw a :any:`LibsemigroupsError` if either: >>> tc = to( ... congruence_kind.twosided, # knd ... kb, # kb - ... Return=ToddCoxeter + ... Return=(ToddCoxeter,) ... ) >>> tc.run() diff --git a/src/libsemigroups_pybind11/to.py b/src/libsemigroups_pybind11/to.py index 7dc8f93c..f6220653 100644 --- a/src/libsemigroups_pybind11/to.py +++ b/src/libsemigroups_pybind11/to.py @@ -46,14 +46,6 @@ from .detail.cxx_wrapper import to_cxx as _to_cxx -def __to_congruence_word(*args): - return _Congruence(_to_congruence_word(*args)) - - -def __to_congruence_string(*args): - return _Congruence(_to_congruence_string(*args)) - - def _nice_name(type_list): """Convert an iterable of type-like things into a string""" single_element = False @@ -75,6 +67,44 @@ def _nice_name(type_list): return f"({', '.join(out)})" +_RETURN_TYPE_TO_CONVERTER_FUNCTION = { + (_Congruence, str): _to_congruence_string, + (_Congruence, List[int]): _to_congruence_word, + (_FroidurePin,): _to_froidure_pin, + (_InversePresentation,): _to_inverse_presentation, + (_InversePresentation, List[int]): _to_inverse_presentation_word, + (_InversePresentation, str): _to_inverse_presentation_string, + (_KnuthBendix,): _to_knuth_bendix, + (_KnuthBendix, "RewriteTrie"): _to_knuth_bendix_RewriteTrie, + (_KnuthBendix, "RewriteFromLeft"): _to_knuth_bendix_RewriteFromLeft, + ( + _KnuthBendix, + List[int], + "RewriteFromLeft", + ): _to_knuth_bendix_word_RewriteFromLeft, + ( + _KnuthBendix, + List[int], + "RewriteTrie", + ): _to_knuth_bendix_word_RewriteTrie, + ( + _KnuthBendix, + str, + "RewriteFromLeft", + ): _to_knuth_bendix_string_RewriteFromLeft, + (_KnuthBendix, str, "RewriteTrie"): _to_knuth_bendix_string_RewriteTrie, + (_Presentation,): _to_presentation, + (_Presentation, str): _to_presentation_string, + (_Presentation, List[int]): _to_presentation_word, + (_ToddCoxeter,): _to_todd_coxeter, + (_ToddCoxeter, str): _to_todd_coxeter_string, + (_ToddCoxeter, List[int]): _to_todd_coxeter_word, +} + +_VALID_TYPES = (_nice_name(x) for x in _RETURN_TYPE_TO_CONVERTER_FUNCTION) +_VALID_TYPES_STRING = "\n * " + "\n * ".join(_VALID_TYPES) + "\n" + + def to(*args, Return): """Convert from one type of `libsemigroups` object to another @@ -102,7 +132,7 @@ def to(*args, Return): >>> presentation.add_rule(p, [0, 0], [0]) >>> presentation.add_rule(p, [1, 1], [1]) >>> kb = KnuthBendix(congruence_kind.twosided, p) - >>> fp = to(kb, Return=FroidurePin) + >>> fp = to(kb, Return=(FroidurePin,)) >>> fp # doctest: +NORMALIZE_WHITESPACE @@ -125,67 +155,11 @@ def to(*args, Return): """ cxx_args = [_to_cxx(arg) for arg in args] - return_type_to_converter_function = { - (_Congruence, str): __to_congruence_string, - (_Congruence, List[int]): __to_congruence_word, - _FroidurePin: lambda *x: _FroidurePin(_to_froidure_pin(*x)), - _InversePresentation: lambda *x: _InversePresentation( - _to_inverse_presentation(*x) - ), - (_InversePresentation, List[int]): lambda *x: _InversePresentation( - _to_inverse_presentation_word(*x) - ), - (_InversePresentation, str): lambda *x: _InversePresentation( - _to_inverse_presentation_string(*x) - ), - _KnuthBendix: lambda *x: _KnuthBendix(_to_knuth_bendix(*x)), - (_KnuthBendix, "RewriteTrie"): lambda *x: _KnuthBendix( - _to_knuth_bendix_RewriteTrie(*x) - ), - (_KnuthBendix, "RewriteFromLeft"): lambda *x: _KnuthBendix( - _to_knuth_bendix_RewriteFromLeft(*x) - ), - ( - _KnuthBendix, - List[int], - "RewriteFromLeft", - ): lambda *x: _KnuthBendix(_to_knuth_bendix_word_RewriteFromLeft(*x)), - ( - _KnuthBendix, - List[int], - "RewriteTrie", - ): lambda *x: _KnuthBendix(_to_knuth_bendix_word_RewriteTrie(*x)), - ( - _KnuthBendix, - str, - "RewriteFromLeft", - ): lambda *x: _KnuthBendix(_to_knuth_bendix_string_RewriteFromLeft(*x)), - (_KnuthBendix, str, "RewriteTrie"): lambda *x: _KnuthBendix( - _to_knuth_bendix_string_RewriteTrie(*x) - ), - _Presentation: lambda *x: _Presentation(_to_presentation(*x)), - (_Presentation, str): lambda *x: _Presentation( - _to_presentation_string(*x) - ), - (_Presentation, List[int]): lambda *x: _Presentation( - _to_presentation_word(*x) - ), - _ToddCoxeter: lambda *x: _ToddCoxeter(_to_todd_coxeter(*x)), - (_ToddCoxeter, str): lambda *x: _ToddCoxeter( - _to_todd_coxeter_string(*x) - ), - (_ToddCoxeter, List[int]): lambda *x: _ToddCoxeter( - _to_todd_coxeter_word(*x) - ), - } - - if Return not in return_type_to_converter_function: - valid_types = (_nice_name(x) for x in return_type_to_converter_function) - valid_types_string = "\n * " + "\n * ".join(valid_types) + "\n" + if Return not in _RETURN_TYPE_TO_CONVERTER_FUNCTION: raise TypeError( "expected the first keyword argument to be one of:" - f"{valid_types_string}" + f"{_VALID_TYPES_STRING}" f"but found: {_nice_name(Return)}" ) - - return return_type_to_converter_function[Return](*cxx_args) + constructor = Return[0] + return constructor(_RETURN_TYPE_TO_CONVERTER_FUNCTION[Return](*cxx_args)) diff --git a/src/to-presentation.cpp b/src/to-presentation.cpp index 32ee0988..13fba828 100644 --- a/src/to-presentation.cpp +++ b/src/to-presentation.cpp @@ -61,6 +61,14 @@ namespace libsemigroups { }); } + template + void bind_kb_to_pres_with_word(py::module& m, std::string const& name) { + std::string fn_name = std::string("to_presentation_") + name; + m.def(fn_name.c_str(), [](KnuthBendix& kb) { + return to>(kb); + }); + } + template void bind_fp_to_pres(py::module& m, std::string const& name) { std::string fn_name = std::string("to_presentation_") + name; @@ -119,6 +127,24 @@ namespace libsemigroups { bind_kb_to_pres(m); bind_kb_to_pres(m); + bind_kb_to_pres_with_word(m, "string"); + bind_kb_to_pres_with_word( + m, "string"); + bind_kb_to_pres_with_word( + m, "string"); + bind_kb_to_pres_with_word( + m, "string"); + bind_kb_to_pres_with_word( + m, "word"); + bind_kb_to_pres_with_word( + m, "word"); + bind_kb_to_pres_with_word( + m, "word"); + bind_kb_to_pres_with_word( + m, "word"); + // From FroidurePin bind_fp_to_pres(m, "string"); bind_fp_to_pres(m, "word"); diff --git a/tests/test_to.py b/tests/test_to.py index a2e7641f..1942d7d3 100644 --- a/tests/test_to.py +++ b/tests/test_to.py @@ -20,6 +20,8 @@ FroidurePinKEString, FroidurePinKEWord, FroidurePinTCE, + PresentationStrings, + PresentationWords, ) from libsemigroups_pybind11 import ( @@ -91,7 +93,7 @@ def cong_from_sample_pres(ReturnType, Word, **kwargs): def check_cong_to_froidure_pin(Type, Word, **kwargs): thing = cong_from_sample_pres(Type, Word, **kwargs) - fp = to(thing, Return=FroidurePin) + fp = to(thing, Return=(FroidurePin,)) fp.run() assert fp.is_finite() assert fp.number_of_idempotents() == 3 @@ -101,26 +103,33 @@ def check_cong_to_froidure_pin(Type, Word, **kwargs): def check_cong_to_todd_coxeter(Type, Word, **kwargs): thing = cong_from_sample_pres(Type, Word, **kwargs) - tc = to(congruence_kind.twosided, thing, Return=ToddCoxeter) + tc = to(congruence_kind.twosided, thing, Return=(ToddCoxeter,)) tc.run() assert tc.number_of_classes() == 3 return tc -def check_knuth_bendix_to_pres(Word, Rewriter): - p = sample_pres(Word) +def check_knuth_bendix_to_pres(WordIn, WordOut, Rewriter): + p = sample_pres(WordIn) kb = KnuthBendix(congruence_kind.twosided, p, Rewriter=Rewriter) - q = to(kb, Return=Presentation) - - assert isinstance(q, type(p)) - - presentation.sort_each_rule(p) - presentation.sort_each_rule(q) - presentation.sort_rules(p) - presentation.sort_rules(q) - - # This is because sample_pres is already confluent - assert p == q + q = to(kb, Return=(Presentation, WordOut)) + + assert len(q.rules) == kb.number_of_active_rules() * 2 + + if WordIn is WordOut: + assert q == to(kb, Return=(Presentation,)) + presentation.sort_each_rule(p) + presentation.sort_each_rule(q) + presentation.sort_rules(p) + presentation.sort_rules(q) + # This is because sample_pres is already confluent + assert p == q + elif WordOut is str: + assert isinstance(to_cxx(q), PresentationStrings) + assert q.alphabet() == "ab" + else: + assert isinstance(to_cxx(q), PresentationWords) + assert q.alphabet() == [0, 1] def check_froidure_pin_to_pres(Word): @@ -149,7 +158,7 @@ def check_todd_coxeter_to_knuth_bendix(Word, Rewriter): def check_todd_coxeter_to_knuth_bendix_default(Word): tc = cong_from_sample_pres(ToddCoxeter, Word) - kb = to(congruence_kind.twosided, tc, Return=KnuthBendix) + kb = to(congruence_kind.twosided, tc, Return=(KnuthBendix,)) assert kb.number_of_classes() == tc.number_of_classes() return kb @@ -224,16 +233,11 @@ def test_to_FroidurePin_007(): # From Kambites -# Why does this segfault ... -# def test_to_FroidurePin_008(): -# k = Kambites(Word=str) -# fp = to(k, Return=FroidurePin) -# assert isinstance(to(k, Return=FroidurePin), FroidurePin) -# ... but this doesn't -# def test_to_FroidurePin_008(): -# k = Kambites(Word=str) -# assert isinstance(to(k, Return=FroidurePin), FroidurePin) +def test_to_FroidurePin_008(): + k = Kambites(Word=str) + fp = to(k, Return=(FroidurePin,)) + assert isinstance(fp, FroidurePin) def test_to_FroidurePin_009(): @@ -242,7 +246,7 @@ def test_to_FroidurePin_009(): presentation.add_rule(p, "ef", "dg") k = Kambites(congruence_kind.twosided, p) - fp = to(k, Return=FroidurePin) + fp = to(k, Return=(FroidurePin,)) fp.enumerate(100) assert fp.current_size() == 8205 assert isinstance(to_cxx(fp), FroidurePinKEMultiStringView) @@ -255,7 +259,7 @@ def test_to_FroidurePin_010(): presentation.add_rule(p, [4, 5], [3, 6]) k = Kambites(congruence_kind.twosided, p) - fp = to(k, Return=FroidurePin) + fp = to(k, Return=(FroidurePin,)) fp.enumerate(100) assert fp.current_size() == 8205 assert isinstance(to_cxx(fp), FroidurePinKEWord) @@ -269,7 +273,7 @@ def test_to_FroidurePin_011(): # Kambites wins here, so this checks FroidurePinKEString c = Congruence(congruence_kind.twosided, p) - fp = to(c, Return=FroidurePin) + fp = to(c, Return=(FroidurePin,)) fp.enumerate(100) assert fp.current_size() == 8205 assert isinstance(to_cxx(fp), FroidurePinKEString) @@ -285,7 +289,7 @@ def test_to_FroidurePin_012(): w.target(1, 0, 1) w.target(2, 0, 1) - fp = to(w, Return=FroidurePin) + fp = to(w, Return=(FroidurePin,)) fp.run() assert fp.number_of_rules() == 1 assert isinstance(fp, FroidurePin) @@ -297,7 +301,7 @@ def test_to_FroidurePin_013(): w.target(1, 0, 1) w.target(2, 0, 1) - fp = to(w, 1, 2, Return=FroidurePin) + fp = to(w, 1, 2, Return=(FroidurePin,)) fp.run() assert fp.number_of_rules() == 1 assert isinstance(fp, FroidurePin) @@ -609,19 +613,23 @@ def test_to_Presentation_023(): def test_to_Presentation_024(): - check_knuth_bendix_to_pres(str, "RewriteFromLeft") + check_knuth_bendix_to_pres(str, str, "RewriteFromLeft") + check_knuth_bendix_to_pres(str, List[int], "RewriteFromLeft") def test_to_Presentation_025(): - check_knuth_bendix_to_pres(str, "RewriteTrie") + check_knuth_bendix_to_pres(str, str, "RewriteTrie") + check_knuth_bendix_to_pres(str, List[int], "RewriteTrie") def test_to_Presentation_026(): - check_knuth_bendix_to_pres(List[int], "RewriteFromLeft") + check_knuth_bendix_to_pres(List[int], str, "RewriteFromLeft") + check_knuth_bendix_to_pres(List[int], List[int], "RewriteFromLeft") def test_to_Presentation_027(): - check_knuth_bendix_to_pres(List[int], "RewriteTrie") + check_knuth_bendix_to_pres(List[int], str, "RewriteTrie") + check_knuth_bendix_to_pres(List[int], List[int], "RewriteTrie") # From FroidurePin @@ -698,24 +706,26 @@ def test_to_InversePresentation_032(): p = Presentation("abc") presentation.add_rule(p, "aaa", "b") presentation.add_rule(p, "bac", "cab") - ip = to(p, Return=InversePresentation) + ip = to(p, Return=(InversePresentation,)) assert ip.alphabet() == "abcdef" assert ip.inverses() == "defabc" assert ip.rules == p.rules q = to(p, Return=(Presentation, List[int])) - iq = to(q, Return=InversePresentation) + iq = to(q, Return=(InversePresentation,)) assert iq.alphabet() == [0, 1, 2, 3, 4, 5] assert iq.inverses() == [3, 4, 5, 0, 1, 2] assert iq.rules == q.rules assert to( - to(p, Return=(Presentation, List[int])), Return=InversePresentation - ) == to(to(p, Return=InversePresentation), Return=(Presentation, List[int])) + to(p, Return=(Presentation, List[int])), Return=(InversePresentation,) + ) == to( + to(p, Return=(InversePresentation,)), Return=(Presentation, List[int]) + ) assert to( - to(q, Return=(Presentation, str)), Return=InversePresentation - ) == to(to(q, Return=InversePresentation), Return=(Presentation, str)) + to(q, Return=(Presentation, str)), Return=(InversePresentation,) + ) == to(to(q, Return=(InversePresentation,)), Return=(Presentation, str)) ############################################################################### @@ -811,8 +821,8 @@ def test_to_Congruence_044(): def test_to_999(): x = 10 with pytest.raises(TypeError): - to(x, Return=FroidurePin) + to(x, Return=(FroidurePin,)) with pytest.raises(TypeError): - to(x, Return=ToddCoxeter) + to(x, Return=(ToddCoxeter,)) with pytest.raises(TypeError): - to(x, Return=str) + to(x, Return=(str,))