Skip to main content
Code Review

Return to Answer

Bounty Awarded with 100 reputation awarded by 301_Moved_Permanently
Supply code and note the command-like aspect of the
Source Link
pjz
  • 2.4k
  • 13
  • 15

Your CLI code might look something like this:

import click
@click.command()
@click.option("--fancy-title", default=False, help="Utilise une barre de titre"
 " un peu plus Gtk3")
@click.option("--serial-port", type=type=click.Path(exists=True),
 help="Spécifie le port série à utiliser pour récupérer les "
 "informations provenant du XBee")
@click.option("--zigbee", default=False, help="Spécifie si le module XBee"
 " est un ZigBee")
@click.option("--baudrate", default=9600, help='Débit du port série '
 'utilisé pour la connexion avec le module XBee')
@click.option("--use-udp", default=False, help='Spécifie si la communication doit se faire '
 'par datagrames UDP.')
@click.option("--port", default=4387, help='ort à utiliser pour l’écoute UDP')
def cli(fancy_title, serial_port, zigbee, baudrate, use_udp, port):
 if serial_port is not None:
 reader = drone_racer.XBeeReader(serial_port, baudrate, zigbee=zigbee)
 elif use_udp:
 reader = drone_racer.UDPReader(port)
 else:
 reader = drone_racer.StdInReader
app = drone_racer.Application(reader, fancy_title)

(No, not an author, or even contributor, just a happy user)

Writing this, I noticed one other thing: the --use-X pattern is potentially inconsistent. Invoking

python droneracer.py --serial-port /dev/ttyUSB0 --baudrate 9600 --use-udp --port 1234

is possible, with half of the arguments ending up unused. The connection types might be better thought of as subcommands:

python droneracer.py serial_port /dev/ttyUSB0 9600
python droneracer.py udp 6329
python droneracer.py stdin

Which would look something more like:

import click
@click.command()
@click.option("--fancy-title", default=False, help="Utilise une barre de titre"
 " un peu plus Gtk3")
@click.pass_context
def cli(ctx, fancy_title):
 """Interface graphique "Drone Racer" """
 pass
@cli.result_callback(reader)
def cli_callback(reader, fancy_title)
 app = drone_racer.Application(reader, fancy_title)
@cli.group()
@click.argument("device", type=type=click.Path(exists=True),
 help="Spécifie le port série à utiliser pour récupérer les "
 "informations provenant du XBee", required=True)
@click.argument("baudrate", default=9600, help='Débit du port série '
 'utilisé pour la connexion avec le module XBee', required=False)
@click.option("--zigbee", default=False, help="Spécifie si le module XBee"
 " est un ZigBee")
def serial_port(device, baudrate, zigbee):
 return drone_racer.XBeeReader(device, baudrate, zigbee=zigbee)
@cli.group()
@click.argument("port", default=4387, required=False)
def udp(port):
 """Spécifie si la communication doit se faire par datagrames UDP."""
 return drone_racer.UDPReader(port)
@cli.group()
def stdin():
 """Specify the use of a serial port"""
 return drone_racer.StdInReader

As a second alternative, you could devise some URL-like specification and parse it. Consider a CLI like:

python droneracer.py udp:4387
python droneracer.py /dev/USB0:9600

It's not pretty and would involve custom parsing, but at least it's unambiguous and avoids the possibility of self-contradiction.

I think I prefer the subcommand architecture; the last suggestion would be okay if there were standard URL formats for the endpoints in question, but there aren't.

(No, not an author, or even contributor, just a happy user)

Your CLI code might look something like this:

import click
@click.command()
@click.option("--fancy-title", default=False, help="Utilise une barre de titre"
 " un peu plus Gtk3")
@click.option("--serial-port", type=type=click.Path(exists=True),
 help="Spécifie le port série à utiliser pour récupérer les "
 "informations provenant du XBee")
@click.option("--zigbee", default=False, help="Spécifie si le module XBee"
 " est un ZigBee")
@click.option("--baudrate", default=9600, help='Débit du port série '
 'utilisé pour la connexion avec le module XBee')
@click.option("--use-udp", default=False, help='Spécifie si la communication doit se faire '
 'par datagrames UDP.')
@click.option("--port", default=4387, help='ort à utiliser pour l’écoute UDP')
def cli(fancy_title, serial_port, zigbee, baudrate, use_udp, port):
 if serial_port is not None:
 reader = drone_racer.XBeeReader(serial_port, baudrate, zigbee=zigbee)
 elif use_udp:
 reader = drone_racer.UDPReader(port)
 else:
 reader = drone_racer.StdInReader
app = drone_racer.Application(reader, fancy_title)

(No, not an author, or even contributor, just a happy user)

Writing this, I noticed one other thing: the --use-X pattern is potentially inconsistent. Invoking

python droneracer.py --serial-port /dev/ttyUSB0 --baudrate 9600 --use-udp --port 1234

is possible, with half of the arguments ending up unused. The connection types might be better thought of as subcommands:

python droneracer.py serial_port /dev/ttyUSB0 9600
python droneracer.py udp 6329
python droneracer.py stdin

Which would look something more like:

import click
@click.command()
@click.option("--fancy-title", default=False, help="Utilise une barre de titre"
 " un peu plus Gtk3")
@click.pass_context
def cli(ctx, fancy_title):
 """Interface graphique "Drone Racer" """
 pass
@cli.result_callback(reader)
def cli_callback(reader, fancy_title)
 app = drone_racer.Application(reader, fancy_title)
@cli.group()
@click.argument("device", type=type=click.Path(exists=True),
 help="Spécifie le port série à utiliser pour récupérer les "
 "informations provenant du XBee", required=True)
@click.argument("baudrate", default=9600, help='Débit du port série '
 'utilisé pour la connexion avec le module XBee', required=False)
@click.option("--zigbee", default=False, help="Spécifie si le module XBee"
 " est un ZigBee")
def serial_port(device, baudrate, zigbee):
 return drone_racer.XBeeReader(device, baudrate, zigbee=zigbee)
@cli.group()
@click.argument("port", default=4387, required=False)
def udp(port):
 """Spécifie si la communication doit se faire par datagrames UDP."""
 return drone_racer.UDPReader(port)
@cli.group()
def stdin():
 """Specify the use of a serial port"""
 return drone_racer.StdInReader

As a second alternative, you could devise some URL-like specification and parse it. Consider a CLI like:

python droneracer.py udp:4387
python droneracer.py /dev/USB0:9600

It's not pretty and would involve custom parsing, but at least it's unambiguous and avoids the possibility of self-contradiction.

I think I prefer the subcommand architecture; the last suggestion would be okay if there were standard URL formats for the endpoints in question, but there aren't.

Source Link
pjz
  • 2.4k
  • 13
  • 15

WRT intuitive CLI argument parsing, you might consider checking out the click library, if not for this project then for the next.

(No, not an author, or even contributor, just a happy user)

lang-py

AltStyle によって変換されたページ (->オリジナル) /