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

If "callback" option with "character" type then logical default converted into a character value #47

Closed
trevorld opened this issue Apr 15, 2024 · 2 comments · Fixed by #48
Assignees
Labels

Comments

@trevorld
Copy link
Owner

Example by @hs3434 in #46

library("optparse")
str2bool <- function(option, flag, option_value, parser) {
    print(option_value)
    s <- tolower(as.character(option_value))
    if (s %in% c("0", "false", "f", "no", "n")) {
        FALSE
    } else {
        TRUE
    }
}
parser <- OptionParser()
parser <- add_option(parser, "--test", type = "character", default = FALSE, callback = str2bool)
parse_args(parser) |> print()
$help
[1] FALSE

$test
[1] "FALSE"
parse_args(parser, "--test=f") |> print()
$help
[1] FALSE

$test
[1] FALSE

This isn't something that the inspiration python module ever did:

import optparse


def str2bool(option, opt, value, parser):
    setattr(parser.values, option.dest, bool(value))


parser = optparse.OptionParser()
parser.add_option("--test", action="callback", type="string",
                  default=False, callback=str2bool)
opts, args = parser.parse_args()
print(opts)
~/tmp$ python3 optparse_bug2.py 
{'test': False}
~/tmp$ python3 optparse_bug2.py --test=True
{'test': True}
@trevorld trevorld added the bug label Apr 15, 2024
@trevorld trevorld self-assigned this Apr 15, 2024
@trevorld
Copy link
Owner Author

I do observe for the python module that for the "store" action and the "int" type that a character default would be converted to an int:

import optparse

parser = optparse.OptionParser()
parser.add_option("--int", type="int", default="2")
opts, args = parser.parse_args()
print(opts)
~/tmp$ python3 optparse_bug.py 
{'int': 2}

@hs3434
Copy link

hs3434 commented Apr 15, 2024

Because the python only handle the numeric and choise,
Here is the code in optparse.py lines 543-548:

TYPE_CHECKER = { "int"    : check_builtin,
                     "long"   : check_builtin,
                     "float"  : check_builtin,
                     "complex": check_builtin,
                     "choice" : check_choice,
                   }

The check_builtin only include numeric , here is the code in optparse.py lines 422- 433:

_builtin_cvt = { "int" : (_parse_int, _("integer")),
                 "long" : (_parse_int, _("integer")),
                 "float" : (float, _("floating-point")),
                 "complex" : (complex, _("complex")) }

def check_builtin(option, opt, value):
    (cvt, what) = _builtin_cvt[option.type]
    try:
        return cvt(value)
    except ValueError:
        raise OptionValueError(
            _("option %s: invalid %s value: %r") % (opt, what, value))

Maybe you can copy this and develop some new features.

trevorld added a commit that referenced this issue Apr 15, 2024
* We no longer coerce the type of an option `default` to match that of
  its `type` argument when `action = "callback"`.
  Thanks husheng (@hs3434) for bug report.

closes #46, closes #47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants