Skip to content

Suggest return types when conversions fail - #496

Merged
james-d-mitchell merged 2 commits into
mainfrom
codex/fix-461-todd-coxeter-word-type
Sep 12, 2026
Merged

james-d-mitchell merged 2 commits into
mainfrom
codex/fix-461-todd-coxeter-word-type

Conversation

@james-d-mitchell

@james-d-mitchell james-d-mitchell commented Sep 9, 2026 •

Copy link
Copy Markdown
Member

to(...) can fail with a binding-level TypeError that lists overloads for the selected converter without explaining the available return types. Catch converter TypeErrors and list the registered rtype choices for the requested output class, preserving the original exception as the cause. The choices apply to that output class; which ones work depends on the input arguments.

Use the same diagnostic for every output class. Keep wrapper construction outside the error handler and let other exception types propagate unchanged. Document the diagnostic and the requirement to specify a word type when converting a FroidurePin and its Cayley graph to ToddCoxeter.

Regression coverage includes all seven output classes, the original Todd–Coxeter example with both congruence kinds and wrapped/unwrapped inputs, missing presentation word types, exception chaining, and preservation of LibsemigroupsError.

Closes #461.

Validation using the source package and existing CPython 3.13 extension:

  • pytest tests/test_to.py tests/test_todd_coxeter.py: 114 passed.
  • make doctest with the lockfile's documentation dependencies: 1,509 passed.
  • make doc: HTML built successfully and the changed text and links were checked. The existing diagram was reused after Inkscape crashed during optional regeneration. The parameter checker reports nine type-hint warnings in unrelated APIs.
  • Both pre-commit and pre-push hook stages passed for the three changed files; C++ hooks had no applicable files.
  • git diff --check passed.

AI disclosure: OpenAI Codex prepared the implementation, tests, documentation, commit messages, and PR description, and ran the validation. Codex is the commit author; James Mitchell is the committer. Both commits include Co-authored-by: Codex <codex@openai.com>.

@james-d-mitchell
james-d-mitchell force-pushed the codex/fix-461-todd-coxeter-word-type branch from 52c0647 to 1e984d8 Compare September 9, 2026 13:18
@james-d-mitchell james-d-mitchell changed the title Clarify missing word type in ToddCoxeter conversions Clarify missing word type in ToddCoxeter conversions Sep 9, 2026
@james-d-mitchell
james-d-mitchell force-pushed the codex/fix-461-todd-coxeter-word-type branch from 72edf25 to 538c7d2 Compare September 10, 2026 08:12

@Joseph-Edwards Joseph-Edwards left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As @james-d-mitchell and I discussed, this solution is probably slightly too specific to ToddCoxeter. A solution along the line of the following might be more suitable:

     constructor = rtype[0]
-    return constructor(_RETURN_TYPE_TO_CONVERTER_FUNCTION[rtype](*cxx_args))
+    try:
+        return constructor(_RETURN_TYPE_TO_CONVERTER_FUNCTION[rtype](*cxx_args))
+    except TypeError as e:
+        possible_constructor_tuples = (
+            _nice_name(x) for x in _RETURN_TYPE_TO_CONVERTER_FUNCTION if constructor in x
+        )
+
+        new_message = "The possible values for the first keyword argument are:" + (
+            "\n    * " + "\n    * ".join(possible_constructor_tuples) + "\n"
+        )
+        raise TypeError(new_message) from e

The idea is that we catch the TypeError that may be thrown by Pybind11's dispatch code, and insert our own custom description that displays some possible rtypes that the user may have meant. The example that I cobbled together above would look like this:

tc = to(congruence_kind.twosided, S, S.right_cayley_graph(), rtype=(ToddCoxeter,))
#0: FroidurePin: enumerating until all elements are found . . .
#0: FroidurePin: ⌀ 1    (Cayley graph) | 2           (elements) | 0         (rules) | 247ns   (total) 
#0: FroidurePin: ⌀ 2    (Cayley graph) | 6           (elements) | 0         (rules) | 27µs    (total) 
#0: FroidurePin: ⌀ 3    (Cayley graph) | 13          (elements) | 1         (rules) | 32µs    (total) 
#0: FroidurePin: ⌀ 4    (Cayley graph) | 25          (elements) | 2         (rules) | 39µs    (total) 
#0: FroidurePin: ⌀ 5    (Cayley graph) | 42          (elements) | 6         (rules) | 47µs    (total) 
#0: FroidurePin: ⌀ 6    (Cayley graph) | 61          (elements) | 11        (rules) | 54µs    (total) 
#0: FroidurePin: ⌀ 7    (Cayley graph) | 76          (elements) | 14        (rules) | 62µs    (total) 
#0: FroidurePin: ⌀ 8    (Cayley graph) | 84          (elements) | 17        (rules) | 65µs    (total) 
#0: FroidurePin: ⌀ 9    (Cayley graph) | 88          (elements) | 17        (rules) | 69µs    (total) 
#0: FroidurePin: 
#0: FroidurePin: number of products was  104 of 176 (59.091%)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
File ~/miniforge3/envs/libsemigroups_pybind11_dev/lib/python3.14/site-packages/libsemigroups_pybind11/to.py:181, in to(rtype, *args)
    180 try:
--> 181     return constructor(_RETURN_TYPE_TO_CONVERTER_FUNCTION[rtype](*cxx_args))
    182 except TypeError as e:

TypeError: to_todd_coxeter(): incompatible function arguments. The following argument types are supported:
    1. (arg0: _libsemigroups_pybind11.congruence_kind, arg1: _libsemigroups_pybind11.KnuthBendixStringLenLexSet) -> _libsemigroups_pybind11.ToddCoxeterString
    2. (arg0: _libsemigroups_pybind11.congruence_kind, arg1: _libsemigroups_pybind11.KnuthBendixStringLenLexTrie) -> _libsemigroups_pybind11.ToddCoxeterString
    3. (arg0: _libsemigroups_pybind11.congruence_kind, arg1: _libsemigroups_pybind11.KnuthBendixWordLenLexSet) -> _libsemigroups_pybind11.ToddCoxeterWord
    4. (arg0: _libsemigroups_pybind11.congruence_kind, arg1: _libsemigroups_pybind11.KnuthBendixWordLenLexTrie) -> _libsemigroups_pybind11.ToddCoxeterWord
    5. (arg0: _libsemigroups_pybind11.congruence_kind, arg1: _libsemigroups_pybind11.KnuthBendixStringRPOSet) -> _libsemigroups_pybind11.ToddCoxeterString
    6. (arg0: _libsemigroups_pybind11.congruence_kind, arg1: _libsemigroups_pybind11.KnuthBendixStringRPOTrie) -> _libsemigroups_pybind11.ToddCoxeterString
    7. (arg0: _libsemigroups_pybind11.congruence_kind, arg1: _libsemigroups_pybind11.KnuthBendixWordRPOSet) -> _libsemigroups_pybind11.ToddCoxeterWord
    8. (arg0: _libsemigroups_pybind11.congruence_kind, arg1: _libsemigroups_pybind11.KnuthBendixWordRPOTrie) -> _libsemigroups_pybind11.ToddCoxeterWord
    9. (arg0: _libsemigroups_pybind11.congruence_kind, arg1: _libsemigroups_pybind11.KnuthBendixStringRevRPOSet) -> _libsemigroups_pybind11.ToddCoxeterString
    10. (arg0: _libsemigroups_pybind11.congruence_kind, arg1: _libsemigroups_pybind11.KnuthBendixStringRevRPOTrie) -> _libsemigroups_pybind11.ToddCoxeterString
    11. (arg0: _libsemigroups_pybind11.congruence_kind, arg1: _libsemigroups_pybind11.KnuthBendixWordRevRPOSet) -> _libsemigroups_pybind11.ToddCoxeterWord
    12. (arg0: _libsemigroups_pybind11.congruence_kind, arg1: _libsemigroups_pybind11.KnuthBendixWordRevRPOTrie) -> _libsemigroups_pybind11.ToddCoxeterWord

Invoked with: <congruence_kind.twosided: 2>, <fully enumerated FroidurePin with 2 generators, 88 elements, Cayley graph ⌀ 9, & 18 rules>, <WordGraph with 88 nodes, 176 edges, & out-degree 2>

The above exception was the direct cause of the following exception:

TypeError                                 Traceback (most recent call last)
Cell In[3], line 1
----> 1 tc = to(congruence_kind.twosided, S, S.right_cayley_graph(), rtype=(ToddCoxeter,))

File ~/miniforge3/envs/libsemigroups_pybind11_dev/lib/python3.14/site-packages/libsemigroups_pybind11/to.py:190, in to(rtype, *args)
    183 possible_constructor_tuples = (
    184     _nice_name(x) for x in _RETURN_TYPE_TO_CONVERTER_FUNCTION if constructor in x
    185 )
    187 new_message = "The possible values for the first keyword argument are:" + (
    188     "\n    * " + "\n    * ".join(possible_constructor_tuples) + "\n"
    189 )
--> 190 raise TypeError(new_message) from e

TypeError: The possible values for the first keyword argument are:
    * (ToddCoxeter)
    * (ToddCoxeter, str)
    * (ToddCoxeter, list[int])

The new exception message probably needs some work.

@james-d-mitchell james-d-mitchell changed the title Clarify missing word type in ToddCoxeter conversions Suggest return types when conversions fail Sep 12, 2026
@james-d-mitchell
james-d-mitchell force-pushed the codex/fix-461-todd-coxeter-word-type branch from 7976924 to e51636e Compare September 12, 2026 12:17
AI disclosure: OpenAI Codex prepared the initial implementation, tests,
documentation, and commit message.

Co-authored-by: Codex <codex@openai.com>
List the registered rtype choices for the requested output class when a
converter raises TypeError, preserving the original exception as its cause.
Cover all output classes, callback errors, and non-TypeError exceptions.

AI disclosure: OpenAI Codex prepared the code, tests, documentation, and
commit message, and ran the validation.

Co-authored-by: Codex <codex@openai.com>
@james-d-mitchell
james-d-mitchell force-pushed the codex/fix-461-todd-coxeter-word-type branch from e51636e to 5c59b3d Compare September 12, 2026 12:22
@james-d-mitchell

Copy link
Copy Markdown
Member Author

@Joseph-Edwards like this?

@Joseph-Edwards Joseph-Edwards left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great. Thanks @james-d-mitchell!

@james-d-mitchell
james-d-mitchell merged commit 9da571a into main Sep 12, 2026
28 checks passed
@james-d-mitchell
james-d-mitchell deleted the codex/fix-461-todd-coxeter-word-type branch September 12, 2026 14:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

to<ToddCoxeter>(congruence_kind, FroidurePin, WordGraph) fails

3 participants