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

Strange behavior of "Optional[T]" and "Suppress" #186

Closed
KrobotP opened this issue Oct 23, 2024 · 2 comments · Fixed by #187
Closed

Strange behavior of "Optional[T]" and "Suppress" #186

KrobotP opened this issue Oct 23, 2024 · 2 comments · Fixed by #187

Comments

@KrobotP
Copy link

KrobotP commented Oct 23, 2024

Once more I am here with my example app:

class MySpec(BaseModel):
    some_set: Set[int] = Field(
        default={1, 2, 3},
        decsription="Some set of integers",
        title="Some set",
    )

    some_string: str = Field(
        decsription="Some string without a default value.",
        title="SomeSTR",
    )


def add_spec(spec: MySpec):
    print(spec.here_comes_the_trouble)

if __name__ == "__main__":
    tyro.cli(add_spec)

Everything works fine here:

$ python3.11 example.py --help
usage: example.py [-h] [--spec.some-set [INT [INT ...]]] --spec.some-string STR

╭─ options ───────────────────────────────────────────────╮
│ -h, --help              show this help message and exit │
╰─────────────────────────────────────────────────────────╯
╭─ spec options ──────────────────────────────────────────╮
│ --spec.some-set [INT [INT ...]]                         │
│                         (default: '{1, 2, 3}')          │
│ --spec.some-string STR  (required)                      │
╰─────────────────────────────────────────────────────────╯

Now I would like to make some-string parameter optional:

class MySpec(BaseModel):
    some_set: Set[int] = Field(
        default={1, 2, 3},
        decsription="Some set of integers",
        title="Some set",
    )

    some_string: Optional[str] = Field(
        decsription="Some string without a default value.",
        title="SomeSTR",
    )

Everything still works, but with a warning:

$ python3.11 example.py --help
/usr/local/lib/python3.11/site-packages/tyro/_fields.py:181: UserWarning: The field some_string is annotated with type <class 'str'>, but the default value None has type <class 'NoneType'>. We'll try to handle this gracefully, but it may cause unexpected behavior.
  warnings.warn(
usage: example.py [-h] [--spec.some-set [INT [INT ...]]] [--spec.some-string {None}|STR]

╭─ options ─────────────────────────────────────────╮
│ -h, --help        show this help message and exit │
╰───────────────────────────────────────────────────╯
╭─ spec options ────────────────────────────────────╮
│ --spec.some-set [INT [INT ...]]                   │
│                   (default: '{1, 2, 3}')          │
│ --spec.some-string {None}|STR                     │
│                   (default: None)                 │
╰───────────────────────────────────────────────────╯

I am not quite sure why there is a warning as some-string is declared as union of "None" and "str", having "None" as default value should be legal.

Moreover, when I try to suppress an optional option, no suppression is made at all:

class MySpec(BaseModel):
    some_set: Set[int] = Field(
        default={1, 2, 3},
        decsription="Some set of integers",
        title="Some set",
    )

    some_string: tyro.conf.Suppress[Optional[str]] = Field(
        decsription="Some string without a default value.",
        title="SomeSTR",
    )
$ python3.11 example.py --help
/usr/local/lib/python3.11/site-packages/tyro/_fields.py:181: UserWarning: The field some_string is annotated with type <class 'str'>, but the default value None has type <class 'NoneType'>. We'll try to handle this gracefully, but it may cause unexpected behavior.
  warnings.warn(
usage: example.py [-h] [--spec.some-set [INT [INT ...]]] [--spec.some-string {None}|STR]

╭─ options ─────────────────────────────────────────╮
│ -h, --help        show this help message and exit │
╰───────────────────────────────────────────────────╯
╭─ spec options ────────────────────────────────────╮
│ --spec.some-set [INT [INT ...]]                   │
│                   (default: '{1, 2, 3}')          │
│ --spec.some-string {None}|STR                     │
│                   (default: None)                 │
╰───────────────────────────────────────────────────╯

Suppression is ignored even when I remove warning by setting default value of type str.

Suppresion works, when Optional is not used, or when I prefix option name with _.

@brentyi
Copy link
Owner

brentyi commented Oct 23, 2024

Hi @KrobotP, can you confirm which version of pydantic you're using?

This:

from typing import Optional, Set

from pydantic import BaseModel, Field

import tyro


class MySpec(BaseModel):
    some_set: Set[int] = Field(
        default={1, 2, 3},
        decsription="Some set of integers",
        title="Some set",
    )

    some_string: tyro.conf.Suppress[Optional[str]] = Field(
        decsription="Some string without a default value.",
        title="SomeSTR",
    )


tyro.cli(MySpec)

appears to give me the right behavior with pydantic==2.9.2; an error that some_string is missing a default value. When I set the default value, the error disappears and the argument is correctly suppressed.

As a note, it seems like you've also misspelled description in all of your examples.

@KrobotP
Copy link
Author

KrobotP commented Oct 24, 2024

Hello @brentyi, I am currently using older version (1.2) as we are in the middle of transfer to the newer 2+. Thus, we wuld like to work with both versions for some time.

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 a pull request may close this issue.

2 participants