6.20.4.4 Esempi

Ecco un'esempio di opzione di callback che non accetta argomenti, e registra solamente il fatto che l'opzione � stata specificata:

def record_foo_seen(option, opt, value, parser):
    parser.saw_foo = 1

parser.add_option("--foo", action="callback", callback=record_foo_seen)

Naturalmente, potreste fare questo con l'azione ``store_true''. Ecco un esempio un po' pi� interessante: viene registrato il fatto che -a � stato specificato, ma se specificato dopo -b sulla riga di comando, viene considerato non valido.

def check_order(option, opt, value, parser):
    if parser.values.b:
        raise OptionValueError("can't use -a after -b")
    parser.values.a = 1
...
parser.add_option("-a", action="callback", callback=check_order)
parser.add_option("-b", action="store_true", dest="b")

Se volete riutilizzare questa funzione di callback per diverse opzioni simili (definire una stringa di opzione, ma invalidarla se -b � stata gi� invocata), � necessario lavorarci sopra: il messaggio di errore e la stringa di opzione su cui viene impostato hanno bisogno di venire generalizzati.

def check_order(option, opt, value, parser):
    if parser.values.b:
        raise OptionValueError("can't use %s after -b" % opt)
    setattr(parser.values, option.dest, 1)
...
parser.add_option("-a", action="callback", callback=check_order, dest='a')
parser.add_option("-b", action="store_true", dest="b")
parser.add_option("-c", action="callback", callback=check_order, dest='c')

Naturalmente, potete valutare qualsiasi condizione -- non siete obbligati a controllare i valori delle opzioni gi� definite. Per esempio, se avete delle opzioni che non dovrebbero venire chiamate quando c'� luna piena, ci� che bisogna fare � questo:

def check_moon(option, opt, value, parser):
    if is_full_moon():
        raise OptionValueError("%s option invalid when moon full" % opt)
    setattr(parser.values, option.dest, 1)
...
parser.add_option("--foo",
                  action="callback", callback=check_moon, dest="foo")

La definizione di is_full_moon() viene lasciato come esercizio al lettore.

Argomenti costanti

Le cose diventano un po' pi� interessanti quando si definiscono opzioni di callback che accettano un numero di argomenti prefissato. La specificazione che una opzione di callback accetti argomenti � simile alla definizione di una opzione ``store'' o ``append'': se definite un tipo, allora l'opzione accetta un argomento che sia convertibile in quel tipo; se in seguito definirete nargs, allora l'opzione accetter� tutti quegli argomenti.

Ecco un esempio che emula l'azione standard ``store'':

def store_value(option, opt, value, parser):
    setattr(parser.values, option.dest, value)
...
parser.add_option("--foo",
                  action="callback", callback=store_value,
                  type="int", nargs=3, dest="foo")

Notate che optparse si occupa di elaborare tre argomenti e di convertirli in interi al posto vostro; tutto quello che voi dovrete fare sar� memorizzarli. (O qualcosa di simile: ovviamente non c'� bisogno di una funzione di callback per questo esempio. Usate la vostra immaginazione!)

Argomenti variabili

Le cose si complicheranno nel momento in cui vorrete un'opzione che accetti un numero variabile di argomenti. In questo caso dovrete scrivere una funzione di callback; optparse non possiede nessuna funzionalit� built-in per poterlo fare Dovrete confrontarvi con la ben strutturata sintassi per poter effettuare l'analisi attraverso la riga di comando convenzionale Unix. (In precedenza optparse si prendeva in carico questo compito, ma non funzionava bene. L'errore � stato corretto, al costo per� di rendere pi� complesso questo tipo di callback.) In particolare, le funzioni di callback devono preoccuparsi degli argomenti nudi -- e -; la convenzione �:

Se desiderate un'opzione che accetti un numero variabile di argomenti, bisogna che abbiate scaltrezza ed ingegno, per via di diverse difficolt� che potrebbero presentarvisi. L'esatta implementazione che verr� scelta dovr� essere basata su quello che desiderate e su quanto sarete disposti a fare per la vostra applicazione (questo � il motivo per cui optparse non supporta direttamente questo tipo di operazioni).

Comunque, ecco un tentativo di una opzione con argomenti variabili su di una funzione di callback:

def varargs(option, opt, value, parser):
    assert value is None
    done = 0
    value = []
    rargs = parser.rargs
    while rargs:
        arg = rargs[0]

        #  Stop se viene intercettato un argomento come "--foo", "-a",
	#+ "-fx", "--file=f", etc. 
	#  Notate che che lo stop avviene anche su "-3" o "-3.0",
	#+ cos� se la vostra opzione accetta valori numerici, dovrete
        #+ gestirli in questo modo. 

        if ((arg[:2] == "--" and len(arg) > 2) or
            (arg[:1] == "-" and len(arg) > 1 and arg[1] != "-")):
            break
        else:
            value.append(arg)
            del rargs[0]

     setattr(parser.values, option.dest, value)

...
parser.add_option("-c", "--callback",
                  action="callback", callback=varargs)

La principale debolezza di questa particolare implementazione, � che i numeri negativi negli argomenti che seguono -c verranno interpretati come opzioni successive, piuttosto che come argomenti di -c. La risoluzione di questo problema viene lasciata per esercizio al lettore.

Vedete Circa questo documento... per informazioni su modifiche e suggerimenti.