Skip to content

Feature: Supressing unbound typevar warning #342

@mirceamironenco

Description

@mirceamironenco

Is there a way to suppress the warning from an unbound typevar?

from collections.abc import Mapping
from dataclasses import dataclass
from typing import Annotated, Callable, Generic

import tyro
from typing_extensions import TypedDict, TypeVar

MapItemT = TypeVar("MapItemT", bound=Mapping)


@dataclass(kw_only=True, frozen=True)
class HFPromptDatasetConfig(Generic[MapItemT]):
    path: str
    prompt_keymap: Annotated[str | Callable[[MapItemT], str], tyro.conf.Suppress]
    answer_keymap: Annotated[str | Callable[[MapItemT], str], tyro.conf.Suppress]

CountdownItem = TypedDict[{"target": int, "nums": list[int]}]

def qwen_prompt(item: CountdownItem) -> str:
    return "foo"


@dataclass
class Config:
    train_data: HFPromptDatasetConfig = HFPromptDatasetConfig(
        path="Jiayi-Pan/Countdown-Tasks-3to4",
        prompt_keymap=qwen_prompt,
        answer_keymap="target",
    )


def main(config: Config) -> None:
    print(config)


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

    main(config)

Note that I've tried to Supress the fields that use the typevar but it doesn't help.
tyro will warn UserWarning: Could not resolve type parameter ~MapItemT. Type parameter resolution is not always possible in @staticmethod or @classmethod., however even though the generic parameter is not set (as in writing HFPromptDatasetConfig[CountdownItem]) the type checker understands that CountdownItem is bound the MapItemT, so I see a mismatch here. For example:

from collections.abc import Mapping
from dataclasses import dataclass
from typing import Annotated, Callable, Generic

import tyro
from typing_extensions import TypedDict, TypeVar

MapItemT = TypeVar("MapItemT", bound=Mapping)


@dataclass(kw_only=True, frozen=True)
class HFPromptDatasetConfig(Generic[MapItemT]):
    path: str
    prompt_keymap: Annotated[str | Callable[[MapItemT], str], tyro.conf.Suppress]
    answer_keymap: Annotated[str | Callable[[MapItemT], str], tyro.conf.Suppress]

CountdownItem = TypedDict[{"target": int, "nums": list[int]}]
SomeOtherItem = TypedDict[{"foo": int, "bar": list[int]}]


def qwen_prompt(item: CountdownItem) -> str:
    return "foo"

def foo_answer(item: SomeOtherItem) -> str: ...


@dataclass
class Config:
    train_data: HFPromptDatasetConfig = HFPromptDatasetConfig(
        path="Jiayi-Pan/Countdown-Tasks-3to4",
        prompt_keymap=qwen_prompt,
        answer_keymap=foo_answer,
    )


def main(config: Config) -> None:
    print(config)


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

    main(config)

Pyright will issue a correct warning here for answer_keymap=foo_answer:

Argument of type "(item: SomeOtherItem) -> str" cannot be assigned to parameter "answer_keymap" of type "str | ((MapItemT@HFPromptDatasetConfig) -> str)" in function "__init__"
  Type "(item: SomeOtherItem) -> str" is not assignable to type "str | ((CountdownItem) -> str)"
    "FunctionType" is not assignable to "str"
    Type "(item: SomeOtherItem) -> str" is not assignable to type "(CountdownItem) -> str"
      Parameter 1: type "CountdownItem" is incompatible with type "SomeOtherItem"
        "foo" is missing from "<TypedDict>"
        "bar" is missing from "<TypedDict>"

Even if I use a TypeVar with a default the warning is still issued:

from collections.abc import Mapping
from dataclasses import dataclass
from typing import Annotated, Callable, Generic

import tyro
from typing_extensions import TypeVar

MapItemT = TypeVar("MapItemT", bound=Mapping, default=Mapping)


@dataclass(kw_only=True, frozen=True)
class HFPromptDatasetConfig(Generic[MapItemT]):
    path: str
    prompt_keymap: Annotated[str | Callable[[MapItemT], str], tyro.conf.Suppress]
    answer_keymap: Annotated[str | Callable[[MapItemT], str], tyro.conf.Suppress]


@dataclass
class Config:
    train_data: HFPromptDatasetConfig = HFPromptDatasetConfig(
        path="Jiayi-Pan/Countdown-Tasks-3to4",
        prompt_keymap="nums",
        answer_keymap="target",
    )


def main(config: Config) -> None:
    print(config)


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

    main(config)

If there is no way to Suppress I would be happy at least if the warnings.warn(...) used a category= and tyro had a specific warning category here that I can then ignore myself, since other warnings might be relevant.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions