Skip to content

Commit 90e3770

Browse files
committed
feat(verbosity): Allow setting silent or verbose output levels
1 parent 6146410 commit 90e3770

File tree

6 files changed

+114
-24
lines changed

6 files changed

+114
-24
lines changed

docs/en/advanced-topics/serial-protocol.rst

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -468,11 +468,11 @@ Here is a sample extract, showing a READ_REG command and response:
468468

469469
::
470470

471-
TRACE +0.000 command op=0x0a data len=4 wait_response=1 timeout=3.000 data=1400f43f
472-
TRACE +0.000 Write 14 bytes: c0000a0400000000001400f43fc0
473-
TRACE +0.005 Read 1 bytes: c0
474-
TRACE +0.000 Read 11 bytes: 010a0200620100000000c0
475-
TRACE +0.000 Received full packet: 010a0200620100000000
471+
TRACE +0.000 --- Cmd READ_REG (0x0a) | data_len 4 | wait_response 1 | timeout 3.000 | data 00100040 ---
472+
TRACE +0.000 Write 14 bytes: c0000a04000000000000100040c0
473+
TRACE +0.046 Read 1 bytes: c0
474+
TRACE +0.000 Read 11 bytes: 010a0200090000000000c0
475+
TRACE +0.000 Received full packet: 010a0200090000000000
476476

477477
The +X.XXX value is the time delta (in seconds) since the last trace line.
478478

@@ -485,18 +485,18 @@ Here is a second example showing part of the initial synchronization sequence (l
485485

486486
::
487487

488-
TRACE +0.000 Write 46 bytes:
489-
c000082400000000 0007071220555555 | ...$........ UUU
490-
5555555555555555 5555555555555555 | UUUUUUUUUUUUUUUU
491-
5555555555555555 5555555555c0 | UUUUUUUUUUUUU.
492-
TRACE +0.011 Read 1 bytes: c0
493-
TRACE +0.000 Read 63 bytes:
494-
0108040007122055 00000000c0c00108 | ...... U........
495-
0400071220550000 0000c0c001080400 | .... U..........
496-
0712205500000000 c0c0010804000712 | .. U............
497-
205500000000c0c0 01080400071220 | U............
498-
TRACE +0.000 Received full packet: 010804000712205500000000
499-
TRACE +0.000 Received full packet: 010804000712205500000000
488+
TRACE +0.000 Write 46 bytes:
489+
c000082400000000 0007071220555555 | ...$........ UUU
490+
5555555555555555 5555555555555555 | UUUUUUUUUUUUUUUU
491+
5555555555555555 5555555555c0 | UUUUUUUUUUUUU.
492+
TRACE +0.012 Read 1 bytes: c0
493+
TRACE +0.000 Read 63 bytes:
494+
0108040007071220 00000000c0c00108 | ....... ........
495+
0400070712200000 0000c0c001080400 | ..... ..........
496+
0707122000000000 c0c0010804000707 | ... ............
497+
122000000000c0c0 01080400070712 | . .............
498+
TRACE +0.000 Received full packet: 010804000707122000000000
499+
TRACE +0.000 Received full packet: 010804000707122000000000
500500

501501
.. important::
502502

docs/en/esptool/advanced-options.rst

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,3 +162,30 @@ at least one FilterValue for each specified FilterType to be considered. Example
162162
* ``--port-filter serial=7c98d1065267ee11bcc4c8ab93cd958c`` matches ports where the serial number contains the specified text.
163163

164164
See also the `Espressif USB customer-allocated PID repository <https://github.com/espressif/usb-pids>`_
165+
166+
Output Verbosity
167+
----------------
168+
169+
Output verbosity can be controlled using the ``--verbose`` and ``--silent`` flags.
170+
171+
Verbose output: ``--verbose``, ``-v``
172+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
173+
.. _verbose:
174+
175+
The ``--verbose``, ``-v`` flag can be used to show all output without any overwriting or collapsing stages into a single line:
176+
177+
.. code-block:: bash
178+
179+
esptool.py --verbose flash-id
180+
181+
See :ref:`the trace option <tracing-communications>` if you want to dump all serial interactions to the standard output for debugging purposes.
182+
183+
Silent output: ``--silent``, ``-s``
184+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
185+
.. _silent:
186+
187+
The ``--silent``, ``-s`` flag can be used to limit the output to errors only:
188+
189+
.. code-block:: bash
190+
191+
esptool.py -s write-flash 0x0 image.bin

docs/en/esptool/scripting.rst

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,10 @@ Esptool allows redirecting output by implementing a custom logger class. This ca
328328
percent = f"{100 * (cur_iter / float(total_iters)):.1f}"
329329
self.print(f"Finished: {percent}%")
330330
331+
def set_verbosity(self, verbosity):
332+
# Set verbosity level not needed in this example
333+
pass
334+
331335
# Replace the default logger with the custom logger
332336
log.set_logger(CustomLogger())
333337
@@ -344,9 +348,10 @@ To ensure compatibility with esptool, the custom logger should re-implement (or
344348
- ``error``: Logs error messages.
345349
- ``stage``: Starts or ends a collapsible output stage.
346350
- ``progress_bar``: Displays a progress bar.
351+
- ``set_verbosity``: Sets the verbosity level for logging.
347352

348353
.. autoclass:: esptool.logger.EsptoolLogger
349-
:members: print, note, warning, error, stage, progress_bar
354+
:members: print, note, warning, error, stage, progress_bar, set_verbosity
350355
:member-order: bysource
351356

352357
These methods are essential for maintaining proper integration and behavior with esptool. Additionally, all output printing should be made using ``log.print()`` (or the respective method, such as ``log.info()`` or ``log.warning()``) instead of the standard ``print()`` function to ensure the output is routed through the custom logger. This ensures consistency and allows the custom logger to handle all output appropriately. You can further customize this logger to fit your application's needs, such as integrating with GUI components or advanced logging frameworks.

esptool/__init__.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,18 @@ def check_flash_size(esp: ESPLoader, address: int, size: int) -> None:
364364
is_flag=True,
365365
help="Enable trace-level output of esptool.py interactions.",
366366
)
367+
@click.option(
368+
"--verbose",
369+
"-v",
370+
is_flag=True,
371+
help="Print all output, disable collapsing output stages.",
372+
)
373+
@click.option(
374+
"--silent",
375+
"-s",
376+
is_flag=True,
377+
help="Silence all output except for errors.",
378+
)
367379
@click.option(
368380
"--override-vddsdio",
369381
type=click.Choice(ESP32ROM.OVERRIDE_VDDSDIO_CHOICES),
@@ -383,6 +395,18 @@ def cli(
383395
):
384396
ctx.ensure_object(dict)
385397
ctx.obj.update(kwargs)
398+
if ctx.obj["verbose"] and ctx.obj["silent"]:
399+
raise FatalError(
400+
"Cannot use both --verbose and --silent options at the same time."
401+
)
402+
if ctx.obj["trace"] and ctx.obj["silent"]:
403+
raise FatalError(
404+
"Cannot use both --trace and --silent options at the same time."
405+
)
406+
if ctx.obj["verbose"]:
407+
log.set_verbosity("verbose")
408+
elif ctx.obj["silent"]:
409+
log.set_verbosity("silent")
386410
ctx.obj["invoked_subcommand"] = ctx.invoked_subcommand
387411
ctx.obj["esp"] = getattr(ctx, "esp", None)
388412
log.print(f"esptool.py v{__version__}")

esptool/logger.py

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ def progress_bar(
5757
"""
5858
pass
5959

60+
@abstractmethod
61+
def set_verbosity(self, verbosity: str):
62+
"""
63+
Set the verbosity level.
64+
"""
65+
pass
66+
6067

6168
class EsptoolLogger(TemplateLogger):
6269
ansi_red: str = ""
@@ -72,14 +79,16 @@ class EsptoolLogger(TemplateLogger):
7279
_kept_lines: list[str] = []
7380

7481
_smart_features: bool = False
82+
_verbosity: str | None = None
83+
_print_anyway: bool = False
7584

7685
def __new__(cls):
7786
"""
7887
Singleton to ensure only one instance of the logger exists.
7988
"""
8089
if not hasattr(cls, "instance"):
8190
cls.instance = super(EsptoolLogger, cls).__new__(cls)
82-
cls.instance._set_smart_features()
91+
cls.instance.set_verbosity("auto")
8392
return cls.instance
8493

8594
@classmethod
@@ -138,19 +147,21 @@ def print(self, *args, **kwargs):
138147
"""
139148
Log a plain message. Count newlines if in a collapsing stage.
140149
"""
150+
if self._verbosity == "silent" and not self._print_anyway:
151+
return
141152
if self._stage_active:
142153
# Count the number of newlines in the message
143154
message = "".join(map(str, args))
144155
self._newline_count += message.count("\n")
145156
if kwargs.get("end", "\n") == "\n":
146157
self._newline_count += 1
147158
print(*args, **kwargs)
159+
self._print_anyway = False
148160

149161
def note(self, message: str):
150162
"""
151163
Log a Note: message in blue and white.
152164
"""
153-
154165
formatted_message = f"{self.ansi_blue}Note:{self.ansi_normal} {message}"
155166
if self._stage_active:
156167
self._kept_lines.append(formatted_message)
@@ -160,7 +171,6 @@ def warning(self, message: str):
160171
"""
161172
Log a Warning: message in yellow and white.
162173
"""
163-
164174
formatted_message = f"{self.ansi_yellow}Warning:{self.ansi_normal} {message}"
165175
if self._stage_active:
166176
self._kept_lines.append(formatted_message)
@@ -170,8 +180,8 @@ def error(self, message: str):
170180
"""
171181
Log an error message in red to stderr.
172182
"""
173-
174183
formatted_message = f"{self.ansi_red}{message}{self.ansi_normal}"
184+
self._print_anyway = True
175185
self.print(formatted_message, file=sys.stderr)
176186

177187
def stage(self, finish: bool = False):
@@ -182,7 +192,6 @@ def stage(self, finish: bool = False):
182192
Warnings and notes will be saved and printed at the end of the stage.
183193
If terminal doesn't support ANSI escape codes, no collapsing happens.
184194
"""
185-
186195
if finish:
187196
if not self._stage_active:
188197
return
@@ -219,7 +228,6 @@ def progress_bar(
219228
Call in a loop to print a progress bar overwriting itself in place.
220229
If terminal doesn't support ANSI escape codes, no overwriting happens.
221230
"""
222-
223231
filled = int(bar_length * cur_iter // total_iters)
224232
if filled == bar_length:
225233
bar = "=" * bar_length
@@ -238,5 +246,28 @@ def progress_bar(
238246
def set_logger(self, new_logger):
239247
self.__class__ = new_logger.__class__
240248

249+
def set_verbosity(self, verbosity: str):
250+
"""
251+
Set the verbosity level to one of the following:
252+
- "auto": Enable smart terminal features and colors if supported by the terminal
253+
- "verbose": Enable verbose output (no collapsing output)
254+
- "silent": Disable all output except errors
255+
- "compact": Enable smart terminal features and colors even if not supported
256+
"""
257+
if verbosity == self._verbosity:
258+
return
259+
260+
self._verbosity = verbosity
261+
if verbosity == "auto":
262+
self._set_smart_features()
263+
elif verbosity == "verbose":
264+
self._set_smart_features(override=False)
265+
elif verbosity == "silent":
266+
pass
267+
elif verbosity == "compact":
268+
self._set_smart_features(override=True)
269+
else:
270+
raise ValueError(f"Invalid verbosity level: {verbosity}")
271+
241272

242273
log = EsptoolLogger()

test/test_logger.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ def progress_bar(
4242
):
4343
pass
4444

45+
def set_verbosity(self, verbosity: str):
46+
pass
47+
4548

4649
# Custom logger that doesn't implement all methods
4750
class CustomLoggerIncomplete:

0 commit comments

Comments
 (0)