-
Notifications
You must be signed in to change notification settings - Fork 161
/
arguments.py
109 lines (88 loc) · 4.32 KB
/
arguments.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import functools
import argparse
import re
from .. import AccessArguments
class DirectArguments(AccessArguments):
# First, define some state-less methods that just add arguments to an argparse instance.
def _arg_error(self, message, *args, **kwargs):
raise argparse.ArgumentTypeError(("applet {!r}: " + message)
.format(self._applet_name, *args, **kwargs))
def _port_spec(self, arg):
if not re.match(r"^[A-Z]+$", arg):
self._arg_error("{} is not a valid port specification", arg)
return arg
def _add_port_argument(self, parser, default):
help = "bind the applet to port SPEC"
if default is not None:
help += " (default: %(default)s)"
parser.add_argument(
"--port", dest="port_spec", metavar="SPEC", type=self._port_spec,
default=default, help=help)
def _add_port_voltage_arguments(self, parser, default):
g_voltage = parser.add_mutually_exclusive_group(required=True)
g_voltage.add_argument(
"-V", "--voltage", metavar="VOLTS", type=float, nargs="?", default=default,
help="set I/O port voltage explicitly")
g_voltage.add_argument(
"-M", "--mirror-voltage", action="store_true", default=False,
help="sense and mirror I/O port voltage")
g_voltage.add_argument(
"--keep-voltage", action="store_true", default=False,
help="do not change I/O port voltage")
def _pin_number(self, arg):
if not re.match(r"^[0-9]+$", arg):
self._arg_error("{} is not a valid pin number", arg)
return int(arg)
def _add_pin_argument(self, parser, name, default, required):
help = "bind the applet I/O line {!r} to pin NUM".format(name)
if default is not None:
help += " (default: %(default)s)"
opt_name = "--pin-" + name.lower().replace("_", "-")
parser.add_argument(
opt_name, metavar="NUM", type=self._pin_number, default=default, required=required,
help=help)
def _pin_set(self, width, arg):
if re.match(r"^[0-9]+:[0-9]+$", arg):
first, last = map(int, arg.split(":"))
numbers = list(range(first, last))
elif re.match(r"^[0-9]+(,[0-9]+)*$", arg):
numbers = list(map(int, arg.split(",")))
else:
self._arg_error("{} is not a valid pin number set", arg)
if len(numbers) != width:
self._arg_error("set {} includes {} pins, but {} pins are required",
arg, len(numbers), width)
return numbers
def _add_pin_set_argument(self, parser, name, width, default, required):
help = "bind the applet I/O lines {!r} to pins SET".format(name)
if default is not None:
help += " (default: %(default)s)"
opt_name = "--pins-" + name.lower().replace("_", "-")
parser.add_argument(
opt_name, dest="pin_set_{}".format(name), metavar="SET",
type=functools.partial(self._pin_set, width), default=default, required=required,
help=help)
# Second, define a stateful interface that has features like automatically assigning
# default pin numbers.
def __init__(self, applet_name, default_port, pin_count):
self._applet_name = applet_name
self._default_port = default_port
self._free_pins = list(range(pin_count))
@staticmethod
def _get_free(free_list):
if len(free_list) > 0:
result = free_list[0]
free_list.remove(result)
return result
def add_build_arguments(self, parser):
self._add_port_argument(parser, self._default_port)
def add_pin_argument(self, parser, name, default=None, required=False):
if default is True:
default = str(self._get_free(self._free_pins))
self._add_pin_argument(parser, name, default, required)
def add_pin_set_argument(self, parser, name, width, default=None, required=False):
if default is True and len(self._free_pins) >= width:
default = ",".join([str(self._get_free(self._free_pins)) for _ in range(width)])
self._add_pin_set_argument(parser, name, width, default, required)
def add_run_arguments(self, parser):
self._add_port_voltage_arguments(parser, default=None)