Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug (Linux, Python 3.12): Cannot handle "GenericAlias" generated by "TypeAliasType" correctly. #177

Closed
opposj opened this issue Oct 18, 2024 · 5 comments

Comments

@opposj
Copy link

opposj commented Oct 18, 2024

Bug Description

When using a GenericAlias generated by a TypeAliasType as the type hint, AssertionError occurs in the following code snippet:

tyro/src/tyro/_resolver.py

Lines 426 to 431 in 8828943

if hasattr(typ, "copy_with"):
return typ.copy_with(new_args) # type: ignore
else:
# `collections` types, like collections.abc.Sequence.
assert hasattr(origin, "__class_getitem__")
return origin.__class_getitem__(new_args) # type: ignore

To Reproduce

import dataclasses
from typing import Annotated

import tyro

type TT[T] = Annotated[T, tyro.conf.arg(name="", constructor=lambda: True)]

@dataclasses.dataclass(frozen=True)
class Config:
    arg: TT[tuple[int, int]]

if __name__ == "__main__":
    config = tyro.cli(Config)

Additional Context

The TT is an instance of "TypeAliasType", which does not possess a __class_getitem__. However, it seems that the __getitem__ method can work as expected to generate a copied "GenericAlias". Deliberate considerations may be required to design the branching conditions in the previous code snippet.

@brentyi
Copy link
Owner

brentyi commented Oct 20, 2024

Hi @opposj, thanks for the succinct reproduction instructions!

This should be fixed in the latest release; if you have any more problems please let me know!

@brentyi
Copy link
Owner

brentyi commented Oct 22, 2024

Sorry, I realized there are actually more issues. Next release will have them fixed...

@opposj
Copy link
Author

opposj commented Oct 23, 2024

Great work👍! I am currently enjoying the powerful extensiveness of tyro in my project. However, I have to customize tyro a little (by adding a new marker) to support parsing non-nested Iterable in a way like "--iterable=[ele1,ele2,[ele3,ele4]] → iterable = [ele1, ele2, [ele3, ele4]]". I wonder whether it is fine to add this optional feature to tyro?

@brentyi
Copy link
Owner

brentyi commented Oct 24, 2024

Sounds cool! If it's flexible enough I'd be happy to review a PR. Maybe this use case could also be covered by the custom constructor API? Which I'm also planning to revamp, cc #185.

@opposj
Copy link
Author

opposj commented Oct 24, 2024

The constructor is what I tried first, where the same issue as #183 happened to me. It seems that after the update of "0.8.14", the help text can be generated in a more intuitive style according to #185 (although I still prefer the separated grouped options for a constructor). However, the metavar and default value in the help text may not convey correct information of the expected type.

For example, when a list of int is required var: list[int] = [1, 2, 3, 4], the metavar is something like [INT [INT ...]], with a default as 1 2 3 4. By applying a constructor def cons(list_str: str) -> list[int], the metavar is then displayed as STR. What I expected is var Converter[list[int]] = [1,2,3,4] resulting in metavar [INT,INT,...] and default [1,2,3,4].

I'm not sure whether a updated constructor API can implement this feature or not. If a future update covers this feature, I think it unnecessary to provide a new marker, which is realized via adapting the inner instantiator and help text generation.

@brentyi brentyi mentioned this issue Oct 26, 2024
4 tasks
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

No branches or pull requests

2 participants