Multi-value options override the value returned from `callback` when not all specified
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
- #3261 di @Dhi13man — chiusa senza merge
- #3485 di @sjh9714 — chiusa senza merge
- #3529 di @dhaval2025 — chiusa senza merge
- #3539 di @yzhkali — chiusa senza merge
- #3543 di @Xavrir — chiusa senza merge
- #3545 di @viraatdas — chiusa senza merge
- #3567 di @vincere-mori — chiusa senza merge
- #3605 di @lxingy3 — chiusa senza merge
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 45/100
Direzione di ricerca
Inizia eseguendo il riproduttore bad.py con --fetch e con --custom seguito da --fetch. Leggi il comportamento di Option.handle_parse_result di Click e l'elaborazione dei callback per le opzioni che condividono un nome di parametro. Il lavoro è completato quando il callback di fetch restituisce il valore recuperato usando --fetch da solo, senza richiedere un callback su --custom né invocare il fetch esterno più di una volta.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
I discovered this when I wanted to add a flag_value-style option to shortcut a custom str parameter option.
I want to have 2 options:
- one that accepts a parameter of any
strvalue like the name of a file or something - another that is a flag that fetches the value from a remote server instead of me specifying it
Since these both represent the same thing, my initial thought was just to pass them under the same parameter name to the function, which seems to almost work.
the problem seems to be that if the "custom" value is not specified while the "flag" option is set, then click will use the flag_value from the "flag" as the default value for the "custom" value.
And click seems to process unspecified options last (which I can see why this was done), but since "custom" is not specified, it processes the default after the "flag" option has already set a value for the function parameter that they share.
# bad.py
import click
SENTINEL = "$_fetch"
def fetch():
# some logic dependent on an external resource
# return requests.get("...").json()["value")
print('resource fetched')
return "foo"
def callback(ctx, param, value):
if value is SENTINEL:
return fetch()
return value
@click.command()
@click.option("--custom", "custom")
@click.option("--fetch", "custom", flag_value=SENTINEL, callback=callback)
def cli(custom):
print(f'custom={custom}')
if __name__ == '__main__':
cli()
results in the SENTINEL internal value being passed to the function when --fetch is specified alone:
# call with just --custom <arg>, get <arg>, as expected
$ python bad.py --custom bar
custom=bar
# call with just --fetch, get SENTINEL, the internal value that should not ever appear in the values
$ python bad.py --fetch
resource fetched
custom=$_fetch
# call with --custom <arg> first and --fetch after, get the fetched resource, as expected
$ python bad.py --custom bar --fetch
resource fetched
custom=foo
It's that last use-case that really rubs the dirt in; paradoxically, I have to specify the longer option I was trying to avoid using in order to get my "shortcut" flag option to work.
However, we can use a workaround to fix it, sort of, by passing the same callback to both options:
# bad.py
# ..
@click.option("--custom", "custom", callback=callback)
@click.option("--fetch", "custom", flag_value=SENTINEL, callback=callback)
# ..
results in fetch being called twice when --fetch is the last specified option:
# call with just --custom <arg>, get <arg>, as expected
$ python bad.py --custom bar
custom=bar
# call with just --fetch, get foo, but the external resource is pinged twice
$ python bad.py --fetch
resource fetched
resource fetched
custom=foo
# call with --custom <arg> first and --fetch after, get the fetched resource, as expected, resource is pinged once
$ python bad.py --custom bar --fetch
resource fetched
custom=foo
I could have some caching mechanism to avoid the repeated call to the external resource, but that should not be necessary, I should not have to add the callback argument to both options.
I can write a custom Option class that resolved this though:
# good.py
import click
class FixOption(click.Option):
def handle_parse_result(self, ctx, opts, args):
val = super().handle_parse_result(ctx, opts, args)
# even though opts is type-hinted as non-mutable, this still works
opts[self.name] = val[0]
return val
SENTINEL = "$_fetch"
def fetch():
# some logic dependent on an external resource
# return requests.get("...").json()["value")
print('resource fetched')
return "foo"
def callback(ctx, param, value):
if value is SENTINEL:
return fetch()
return value
@click.command()
@click.option("--custom", "custom")
@click.option("--fetch", "custom", flag_value=SENTINEL, callback=callback, cls=FixOption)
def cli(custom):
print(f'custom={custom}')
if __name__ == '__main__':
cli()
But I'd prefer not to have to keep a whole class around just for this, especially when it does work without one, just only if I pass both my options.
Environment:
- Python version: 3.12.5
- Click version: 8.1.7
- Lingua principale
- Python
- Stelle
- 17.8k
- Fork
- 3.3k
- Merge medio
- 3g 3h
- PR unite (30g)
- 13
Preparare l'ambiente
Avvia il container di sviluppo del progetto nel browser, con il tuo account GitHub.
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di pallets/click
-
`show_envvar=True` Drops Environment Variable from Error Messages When Using `auto_envvar_prefix`Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 66/100
I maintainer di solito rispondono entro 1 giorno
-
More private utilities that need to be marked and public api deprecatedForse di nuovo libera Una pull request per questa issue è stata chiusa senza essere unita. Apertatyping
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
pallets/click#3847 · 9 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
Automatically append ellipsis (`...`) to metavars when `multiple=True` in optionsForse già presa @SparshGarg999 l’ha presa 89 giorni fa. Apertahelp output
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
pallets/click#3652 · 4 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
`HelpFormatter.write_usage` breaks options at a hyphenForse già presa @kdeldycke l’ha presa 9 giorni fa. Apertahelp output
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
pallets/click#3362 · 4 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
Add glossary of terms to click reference docsForse già presa @rohitbarhate111-commits l’ha presa 55 giorni fa. Apertadocs
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
pallets/click#3077 · 5 commenti ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di pallets/click
Issue simili
-
needs-triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
gke-labs/kube-agents#5671 ·
I maintainer di solito rispondono entro 1 giorno
-
docs(auth): Method B step 4 should tell users to tick "Use this client for an AI-powered agent"Apertadocumentation next-release v0.9.6
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 88/100
khuisman/mcp-gee-sweet#1446 ·
I maintainer di solito rispondono entro 1 giorno
-
In-box secret files written before their chmod: lc-creds, stacks tee, and the workspace tokenApertamodel:sonnet runtime:claude security size:S
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
FootprintAI/Containarium#3671 ·
I maintainer di solito rispondono entro 1 giorno
-
HolidayBase: reassigning `language` does not re-initialize translations or re-populate holidaysForse già presa @shikhabhadoria l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
vacanza/holidays#4116 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
bug CLI exec
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
I maintainer di solito rispondono entro 1 giorno