33# parttool is used to perform partition level operations - reading,
44# writing, erasing and getting info about the partition.
55#
6- # SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD
6+ # SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD
77# SPDX-License-Identifier: Apache-2.0
88import argparse
99import os
@@ -30,8 +30,7 @@ def status(msg):
3030 print (msg )
3131
3232
33- class _PartitionId ():
34-
33+ class _PartitionId :
3534 def __init__ (self , name = None , p_type = None , subtype = None , part_list = None ):
3635 self .name = name
3736 self .type = p_type
@@ -40,24 +39,32 @@ def __init__(self, name=None, p_type=None, subtype=None, part_list=None):
4039
4140
4241class PartitionName (_PartitionId ):
43-
4442 def __init__ (self , name ):
4543 _PartitionId .__init__ (self , name = name )
4644
4745
4846class PartitionType (_PartitionId ):
49-
5047 def __init__ (self , p_type , subtype , part_list = None ):
5148 _PartitionId .__init__ (self , p_type = p_type , subtype = subtype , part_list = part_list )
5249
5350
5451PARTITION_BOOT_DEFAULT = _PartitionId ()
5552
5653
57- class ParttoolTarget ():
58-
59- def __init__ (self , port = None , baud = None , partition_table_offset = PARTITION_TABLE_OFFSET , primary_bootloader_offset = None , recovery_bootloader_offset = None ,
60- partition_table_file = None , esptool_args = [], esptool_write_args = [], esptool_read_args = [], esptool_erase_args = []):
54+ class ParttoolTarget :
55+ def __init__ (
56+ self ,
57+ port = None ,
58+ baud = None ,
59+ partition_table_offset = PARTITION_TABLE_OFFSET ,
60+ primary_bootloader_offset = None ,
61+ recovery_bootloader_offset = None ,
62+ partition_table_file = None ,
63+ esptool_args = [],
64+ esptool_write_args = [],
65+ esptool_read_args = [],
66+ esptool_erase_args = [],
67+ ):
6168 self .port = port
6269 self .baud = baud
6370
@@ -92,7 +99,9 @@ def parse_esptool_args(esptool_args):
9299 temp_file .close ()
93100
94101 try :
95- self ._call_esptool (['read_flash' , str (partition_table_offset ), str (gen .MAX_PARTITION_LENGTH ), temp_file .name ])
102+ self ._call_esptool (
103+ ['read_flash' , str (partition_table_offset ), str (gen .MAX_PARTITION_LENGTH ), temp_file .name ]
104+ )
96105 with open (temp_file .name , 'rb' ) as f :
97106 partition_table = gen .PartitionTable .from_binary (f .read ())
98107 finally :
@@ -144,30 +153,30 @@ def get_partition_info(self, partition_id):
144153
145154 def erase_partition (self , partition_id ):
146155 partition = self .get_partition_info (partition_id )
147- self ._call_esptool (['erase_region' , str (partition .offset ), str (partition .size )] + self .esptool_erase_args )
156+ self ._call_esptool (['erase_region' , str (partition .offset ), str (partition .size )] + self .esptool_erase_args )
148157
149158 def read_partition (self , partition_id , output ):
150159 partition = self .get_partition_info (partition_id )
151160 self ._call_esptool (['read_flash' , str (partition .offset ), str (partition .size ), output ] + self .esptool_read_args )
152161
153- def write_partition (self , partition_id , input , ignore_readonly = False ):
162+ def write_partition (self , partition_id , input , ignore_readonly = False ): # noqa: A002
154163 partition = self .get_partition_info (partition_id )
155164
156165 if partition .readonly and not ignore_readonly :
157166 raise SystemExit (f'"{ partition .name } " partition is read-only, (use the --ignore-readonly flag to skip it)' )
158167
159168 self .erase_partition (partition_id )
160169
161- with open (input , 'rb' ) as input_file :
162- content_len = len (input_file .read ())
170+ with open (input , 'rb' ) as f :
171+ content_len = len (f .read ())
163172
164173 if content_len > partition .size :
165174 raise Exception ('Input file size exceeds partition size' )
166175
167176 self ._call_esptool (['write_flash' , str (partition .offset ), input ] + self .esptool_write_args )
168177
169178
170- def _write_partition (target , partition_id , input , ignore_readonly = False ):
179+ def _write_partition (target , partition_id , input , ignore_readonly = False ): # noqa: A002
171180 target .write_partition (partition_id , input , ignore_readonly )
172181 partition = target .get_partition_info (partition_id )
173182 status ("Written contents of file '{}' at offset 0x{:x}" .format (input , partition .offset ))
@@ -176,8 +185,11 @@ def _write_partition(target, partition_id, input, ignore_readonly=False):
176185def _read_partition (target , partition_id , output ):
177186 target .read_partition (partition_id , output )
178187 partition = target .get_partition_info (partition_id )
179- status ("Read partition '{}' contents from device at offset 0x{:x} to file '{}'"
180- .format (partition .name , partition .offset , output ))
188+ status (
189+ "Read partition '{}' contents from device at offset 0x{:x} to file '{}'" .format (
190+ partition .name , partition .offset , output
191+ )
192+ )
181193
182194
183195def _erase_partition (target , partition_id ):
@@ -205,7 +217,7 @@ def _get_partition_info(target, partition_id, info):
205217 'offset' : '0x{:x}' .format (p .offset ),
206218 'size' : '0x{:x}' .format (p .size ),
207219 'encrypted' : '{}' .format (p .encrypted ),
208- 'readonly' : '{}' .format (p .readonly )
220+ 'readonly' : '{}' .format (p .readonly ),
209221 }
210222 for i in info :
211223 infos += [info_dict [i ]]
@@ -224,19 +236,29 @@ def main():
224236 parser .add_argument ('--esptool-args' , help = 'additional main arguments for esptool' , nargs = '+' )
225237 parser .add_argument ('--esptool-write-args' , help = 'additional subcommand arguments when writing to flash' , nargs = '+' )
226238 parser .add_argument ('--esptool-read-args' , help = 'additional subcommand arguments when reading flash' , nargs = '+' )
227- parser .add_argument ('--esptool-erase-args' , help = 'additional subcommand arguments when erasing regions of flash' , nargs = '+' )
239+ parser .add_argument (
240+ '--esptool-erase-args' , help = 'additional subcommand arguments when erasing regions of flash' , nargs = '+'
241+ )
228242
229243 # By default the device attached to the specified port is queried for the partition table. If a partition table file
230244 # is specified, that is used instead.
231- parser .add_argument ('--port' , '-p' , help = 'port where the target device of the command is connected to; the partition table is sourced from this device \
232- when the partition table file is not defined' )
245+ parser .add_argument (
246+ '--port' ,
247+ '-p' ,
248+ help = 'port where the target device of the command is connected to; the partition table is sourced from '
249+ 'this device when the partition table file is not defined' ,
250+ )
233251 parser .add_argument ('--baud' , '-b' , help = 'baudrate to use' , type = int )
234252
235253 parser .add_argument ('--partition-table-offset' , '-o' , help = 'offset to read the partition table from' , type = str )
236254 parser .add_argument ('--primary-bootloader-offset' , help = 'offset for primary bootloader' , type = str )
237255 parser .add_argument ('--recovery-bootloader-offset' , help = 'offset for recovery bootloader' , type = str )
238- parser .add_argument ('--partition-table-file' , '-f' , help = 'file (CSV/binary) to read the partition table from; \
239- overrides device attached to specified port as the partition table source when defined' )
256+ parser .add_argument (
257+ '--partition-table-file' ,
258+ '-f' ,
259+ help = 'file (CSV/binary) to read the partition table from; '
260+ 'overrides device attached to specified port as the partition table source when defined' ,
261+ )
240262
241263 partition_selection_parser = argparse .ArgumentParser (add_help = False )
242264
@@ -246,31 +268,54 @@ def main():
246268
247269 partition_selection_args .add_argument ('--partition-name' , '-n' , help = 'name of the partition' )
248270 partition_selection_args .add_argument ('--partition-type' , '-t' , help = 'type of the partition' )
249- partition_selection_args .add_argument ('--partition-boot-default' , '-d' , help = 'select the default boot partition \
250- using the same fallback logic as the IDF bootloader' , action = 'store_true' )
271+ partition_selection_args .add_argument (
272+ '--partition-boot-default' ,
273+ '-d' ,
274+ help = 'select the default boot partition \
275+ using the same fallback logic as the IDF bootloader' ,
276+ action = 'store_true' ,
277+ )
251278
252279 partition_selection_parser .add_argument ('--partition-subtype' , '-s' , help = 'subtype of the partition' )
253- partition_selection_parser .add_argument ('--extra-partition-subtypes' , help = 'Extra partition subtype entries' , nargs = '*' )
280+ partition_selection_parser .add_argument (
281+ '--extra-partition-subtypes' , help = 'Extra partition subtype entries' , nargs = '*'
282+ )
254283
255284 subparsers = parser .add_subparsers (dest = 'operation' , help = 'run parttool -h for additional help' )
256285
257286 # Specify the supported operations
258- read_part_subparser = subparsers .add_parser ('read_partition' , help = 'read partition from device and dump contents into a file' ,
259- parents = [partition_selection_parser ])
287+ read_part_subparser = subparsers .add_parser (
288+ 'read_partition' ,
289+ help = 'read partition from device and dump contents into a file' ,
290+ parents = [partition_selection_parser ],
291+ )
260292 read_part_subparser .add_argument ('--output' , help = 'file to dump the read partition contents to' )
261293
262- write_part_subparser = subparsers .add_parser ('write_partition' , help = 'write contents of a binary file to partition on device' ,
263- parents = [partition_selection_parser ])
294+ write_part_subparser = subparsers .add_parser (
295+ 'write_partition' ,
296+ help = 'write contents of a binary file to partition on device' ,
297+ parents = [partition_selection_parser ],
298+ )
264299 write_part_subparser .add_argument ('--input' , help = 'file whose contents are to be written to the partition offset' )
265300 write_part_subparser .add_argument ('--ignore-readonly' , help = 'Ignore read-only attribute' , action = 'store_true' )
266301
267- subparsers .add_parser ('erase_partition' , help = 'erase the contents of a partition on the device' , parents = [partition_selection_parser ])
268-
269- print_partition_info_subparser = subparsers .add_parser ('get_partition_info' , help = 'get partition information' , parents = [partition_selection_parser ])
270- print_partition_info_subparser .add_argument ('--info' , help = 'type of partition information to get' ,
271- choices = ['name' , 'type' , 'subtype' , 'offset' , 'size' , 'encrypted' , 'readonly' ],
272- default = ['offset' , 'size' ], nargs = '+' )
273- print_partition_info_subparser .add_argument ('--part_list' , help = 'Get a list of partitions suitable for a given type' , action = 'store_true' )
302+ subparsers .add_parser (
303+ 'erase_partition' , help = 'erase the contents of a partition on the device' , parents = [partition_selection_parser ]
304+ )
305+
306+ print_partition_info_subparser = subparsers .add_parser (
307+ 'get_partition_info' , help = 'get partition information' , parents = [partition_selection_parser ]
308+ )
309+ print_partition_info_subparser .add_argument (
310+ '--info' ,
311+ help = 'type of partition information to get' ,
312+ choices = ['name' , 'type' , 'subtype' , 'offset' , 'size' , 'encrypted' , 'readonly' ],
313+ default = ['offset' , 'size' ],
314+ nargs = '+' ,
315+ )
316+ print_partition_info_subparser .add_argument (
317+ '--part_list' , help = 'Get a list of partitions suitable for a given type' , action = 'store_true'
318+ )
274319
275320 args = parser .parse_args ()
276321 quiet = args .quiet
@@ -291,8 +336,10 @@ def main():
291336 elif args .partition_boot_default :
292337 partition_id = PARTITION_BOOT_DEFAULT
293338 else :
294- raise RuntimeError ('Partition to operate on should be defined using --partition-name OR \
295- partition-type,--partition-subtype OR partition-boot-default' )
339+ raise RuntimeError (
340+ 'Partition to operate on should be defined using --partition-name OR \
341+ partition-type,--partition-subtype OR partition-boot-default'
342+ )
296343
297344 # Prepare the device to perform operation on
298345 target_args = {}
@@ -333,18 +380,18 @@ def main():
333380 target = ParttoolTarget (** target_args )
334381
335382 # Create the operation table and execute the operation
336- common_args = {'target' :target , 'partition_id' :partition_id }
383+ common_args = {'target' : target , 'partition_id' : partition_id }
337384 parttool_ops = {
338385 'erase_partition' : (_erase_partition , []),
339386 'read_partition' : (_read_partition , ['output' ]),
340387 'write_partition' : (_write_partition , ['input' , 'ignore_readonly' ]),
341- 'get_partition_info' : (_get_partition_info , ['info' ])
388+ 'get_partition_info' : (_get_partition_info , ['info' ]),
342389 }
343390
344391 (op , op_args ) = parttool_ops [args .operation ]
345392
346393 for op_arg in op_args :
347- common_args .update ({op_arg :vars (args )[op_arg ]})
394+ common_args .update ({op_arg : vars (args )[op_arg ]})
348395
349396 if quiet :
350397 # If exceptions occur, suppress and exit quietly
0 commit comments