fix(stdlib): resolve postponed annotations in generative stub signature - #1504
Merged
Conversation
inspect.signature(func) returns literal annotation strings when the caller's module has `from __future__ import annotations` (PEP 563), corrupting both the rendered function signature and the argument value-quoting check in describe_function()/get_argument(). Pass eval_str=True so annotations resolve the same way typing.get_type_hints() already resolves them elsewhere in the codebase. Fixes generative-computing#1503 Assisted-by: Claude Code Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
Regression test comments cited generative-computing#1476 (the original, unrelated report) instead of generative-computing#1503 (this fix); per project convention, drop the numeric ref rather than just correct it. Also pin each test's precondition via __annotations__ so it can't pass vacuously if the fixture module ever drops `from __future__ import annotations`. Assisted-by: Claude Code Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
Match the module-top-level import style used in PR generative-computing#1509's test/backends/test_tools_pep563.py for the same fixture pattern. Assisted-by: Claude Code Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
jakelorocco
approved these changes
Aug 6, 2026
Merged
via the queue into
generative-computing:main
with commit Aug 6, 2026
c472907
10 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pull Request
Issue
Fixes #1503
Description
Under
from __future__ import annotations(PEP 563 postponed annotations),@generativestub signatures were corrupted before being sent to the model.describe_function()usedinspect.signature(func), which renders postponed annotations as literal strings —(product_description: str) -> list[Requirement]became(product_description: 'str') -> 'list[Requirement]'in the prompt.get_argument()had the same issue at the parameter level:param.annotationwas the string"str"rather than the typestr, so theparam_type is strcheck failed and string arguments were rendered unquoted (value: Aliceinstead ofvalue: "Alice").Both are fixed by passing
eval_str=Truetoinspect.signature(), which resolves the annotation strings back to real types — the same resolutioncreate_response_format()already gets for free viatyping.get_type_hints().Why
eval_str=Trueis safe here: any annotation that would raise undereval_str=True(e.g.TYPE_CHECKING-only imports, forward references to not-yet-defined classes) already raises the identicalNameErrorfrom the pre-existingget_type_hints(func)call increate_response_format(), which every@generative-decorated function goes through at decoration time. So this cannot break any function that could previously be decorated with@generative— it only changes which of two co-located calls raises first.The two other
inspect.signature(func)call sites in this file (bind_function_arguments()andGenerativeStub.__init__'s disallowed-param-name check) are deliberately left unchanged — neither inspects.annotation, so PEP 563 doesn't affect them, and addingeval_strthere would only add a failure mode for no benefit.Follow-ups (out of scope here):
mellea/backends/tools.py'sconvert_function_to_ollama_toolhas the same root-cause bug for tool-schema generation from annotated functions — filed as convert_function_to_ollama_tool breaks under from __future__ import annotations (PEP 563) #1507, fixed in fix(backends): resolve postponed annotations in ollama tool schema #1509.@generative→ prompt-template chain under PEP 563 (the new tests calldescribe_function/get_argumentdirectly); worth adding later.Testing
Added
test/stdlib/components/_pep563_fixtures.py, a fixture module withfrom __future__ import annotations(isolated in its own file since the import is a module-level directive), and two regression tests intest/stdlib/components/test_genstub_unit.py— each with a precondition guard on__annotations__so they can't pass vacuously if PEP 563 is later dropped from the fixture module.uv run python -m pytest test/stdlib/components/test_genstub_unit.py -v— 33 passed.uv run ruff format --check,uv run ruff check,uv run mypy— all clean on the three changed files.Attribution
Adding a new component, requirement, sampling strategy, or tool?
If your PR adds or modifies one of the types below, check the matching box. A checklist of type-specific review items will be posted as a comment.
NOTE: Please ensure you have an issue that has been acknowledged by a core contributor and routed you to open a pull request against this repository. Otherwise, please open an issue before continuing with this pull request.