Skip to content

Commit 307ee6e

Browse files
committed
Refactor: Minor refactor and fixups for typos.
- main.py: Minor fixup for usage string. - firmware_fileio.py: Minor clarification of debugging statement. - logger.py: One line typo in comment. - argparse_typed.py: Minor refactor to improve clarity and maintainability.
1 parent 3e9bc6c commit 307ee6e

File tree

4 files changed

+38
-34
lines changed

4 files changed

+38
-34
lines changed

src/mp_image_tool_esp32/argparse_typed.py

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -46,19 +46,19 @@ def __init__(self, parser: ArgumentParser, typed_namespace: Namespace | None):
4646
# `typed_namespace` may also contain a type conversion function for some types
4747
self.type_conversions = getattr(typed_namespace, "_type_conversions", {})
4848

49-
def _get_argument_type(self, name: str) -> Any:
50-
# Get the field name by replacing "-" with "_" in the last word of options
51-
name = name.lstrip("-").replace("-", "_")
52-
argtype = self.argument_types.get(name) # Get the argument type hint
53-
if not argtype:
54-
raise ValueError(f"Argument `{name}` not found in {self.typed_namespace}")
49+
def _get_argument_type(self, argument_name: str) -> Any:
50+
# Get the argument type hint from the typed_namespace
51+
argument_type = self.argument_types.get(argument_name)
52+
if not argument_type:
53+
raise ValueError(f"Argument `{argument_name}` not found in {self.typed_namespace}")
5554
# The type_conversions map may contain a function to convert the argument type
56-
return self.type_conversions.get(argtype, argtype)
55+
return self.type_conversions.get(argument_type, argument_type)
5756

5857
def add_argument(
59-
self, options: Sequence[str], metavars: Sequence[str], action: str, help: str
58+
self, arguments: Sequence[str], metavars: Sequence[str], action: str, help: str
6059
) -> None:
6160
kwargs: dict[str, Any] = {}
61+
# Sort out the metavar options first
6262
if len(metavars) > 1:
6363
if metavars[-1] == "...":
6464
kwargs["metavar"] = metavars[0]
@@ -70,15 +70,11 @@ def add_argument(
7070
kwargs["metavar"] = metavars[0]
7171

7272
# Get the type hint for the argument from the typed_namespace
73-
argtype = self._get_argument_type(options[-1])
74-
if (
75-
argtype
76-
and argtype is not bool
77-
and argtype is not str
78-
and len(metavars) == 1
79-
):
80-
kwargs["type"] = argtype
81-
elif argtype is bool and not action:
73+
argument_name = arguments[-1].lstrip("-").replace("-", "_")
74+
argument_type = self._get_argument_type(argument_name)
75+
if argument_type and argument_type not in (bool, str) and len(metavars) == 1:
76+
kwargs["type"] = argument_type
77+
elif argument_type is bool and not action:
8278
# default for bool, unless action or fun have been set
8379
action = "store_true"
8480

@@ -87,7 +83,7 @@ def add_argument(
8783
if help:
8884
kwargs["help"] = help
8985

90-
self.parser.add_argument(*options, **kwargs)
86+
self.parser.add_argument(*arguments, **kwargs)
9187

9288

9389
# usage is a multiline string of the form:
@@ -131,21 +127,29 @@ def parser(usage: str, typed_namespace: Namespace | None = None) -> ArgumentPars
131127
prog, description, arguments, epilog = (
132128
paragraph.strip() for paragraph in f"{usage}\n\n".split("\n\n", 3)
133129
)
134-
typed_parser = TypedArgumentParser(
135-
ArgumentParser(prog=prog, description=description, epilog=epilog),
136-
typed_namespace,
137-
)
130+
131+
# Construct a regular argparse ArgumentParser
132+
argparser = ArgumentParser(prog=prog, description=description, epilog=epilog)
133+
# Construct a TypedArgumentParser using the regular parser and the typed_namespace
134+
typed_parser = TypedArgumentParser(argparser, typed_namespace)
138135

139136
# Process each of the arguments in the `arguments` string (one per line)
140137
for line in arguments.splitlines():
138+
# Split the line into parts: ARGUMENTS | HELP STRING | ACTION
139+
# eg. "-i --ignore | Ignore file | T"
141140
argstr, help, action, *_ = (s.strip() for s in f"{line}|||".split("|", 3))
142141

143142
# options contains leading words starting with "-" if any, else all words.
144-
# eg. "-i --input FILE" -> opts = ["-i", "--input"], metavars = ["FILE"]
145-
# eg. "filename" -> opts = ["filename"], metavars = []
146-
words = argstr.split()
147-
options = list(takewhile(lambda s: s.startswith("-"), words)) or words
148-
metavars = words[len(options) :] # trailing words not in options.
149-
typed_parser.add_argument(options, metavars, action, help)
143+
# eg. "-i --input FILE" -> options = ["-i", "--input"], metavars = ["FILE"]
144+
# eg. "filename" -> options = ["filename"], metavars = []
145+
argument_names = argstr.split()
146+
option_names = list(takewhile(lambda s: s.startswith("-"), argument_names))
147+
if not option_names:
148+
# There are no options, so all words are argument names.
149+
typed_parser.add_argument(argument_names, [], action, help)
150+
else:
151+
# If an option is provided, the metavars are the rest of the words.
152+
metavars = argument_names[len(option_names) :]
153+
typed_parser.add_argument(option_names, metavars, action, help)
150154

151155
return typed_parser.parser

src/mp_image_tool_esp32/firmware_fileio.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ def __enter__(self) -> FirmwareDeviceIO:
140140

141141
def read(self, size: int | None = None) -> bytes:
142142
size = size if size is not None else self._end - self._pos
143-
log.debug(f"Reading {size:#x} bytes from {self._pos:#x}...")
143+
log.debug(f"Reading {size:#x} bytes from offset {self._pos:#x}...")
144144
data = self.esptool.read_flash(self._pos, size)
145145
if len(data) != size:
146146
raise ValueError(f"Read {len(data)} bytes from device, expected {size}.")

src/mp_image_tool_esp32/logger.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def render_message(
4747
console=console,
4848
highlighter=NullHighlighter(),
4949
markup=True,
50-
show_time=False, # Don't show the timem level or path in log messages
50+
show_time=False, # Don't show the time, level or path in log messages
5151
show_level=False,
5252
show_path=False,
5353
rich_tracebacks=True,

src/mp_image_tool_esp32/main.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,15 +124,15 @@ class TypedNamespace(argparse.Namespace):
124124
"--table default" (default (non-OTA) partition table),\
125125
"--table nvs=7B,factory=2M,vfs=0". \
126126
SUBTYPE is optional in most cases (inferred from name).
127-
--delete NAME1[,NAME2] | delete the named partitions
127+
--delete NAME1[,NAME2,...] | delete the named partitions
128128
--add NAME1:SUBTYPE:OFFSET:SIZE[,NAME2,...] \
129129
| add new partitions to table
130-
--resize NAME1=SIZE1[,NAME2=SIZE2] \
130+
--resize NAME1=SIZE1[,NAME2=SIZE2,...] \
131131
| resize partitions \
132132
eg. --resize factory=2M,nvs=5B,vfs=0. \
133133
If SIZE is 0, expand partition to available space
134-
--erase NAME1[,NAME2] | erase the named partitions
135-
--erase-fs NAME1[,NAME2] \
134+
--erase NAME1[,NAME2,...] | erase the named partitions
135+
--erase-fs NAME1[,NAME2,...] \
136136
| erase first 4 blocks of a partition on flash storage.\
137137
Micropython will initialise filesystem on next boot.
138138
--read NAME1=FILE1[,NAME2=FILE2,bootloader=FILE,...] \

0 commit comments

Comments
 (0)