comparison cutils/treesum.py @ 335:7620142aacd1

treesum: prepare for a grouping-separator (aka thousands separator) for sizes. BUGS: Not yet implemented but command line options prepared.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 31 Mar 2025 09:02:43 +0200
parents 5afece258bf2
children 0049f486e1cd
comparison
equal deleted inserted replaced
334:5afece258bf2 335:7620142aacd1
104 help="""Put a `GENERATOR' line into the output. 104 help="""Put a `GENERATOR' line into the output.
105 `full' prints full Python and OS/platform version information, 105 `full' prints full Python and OS/platform version information,
106 `normal' prints just whether Python 2 or Python 3 is used, and `none' 106 `normal' prints just whether Python 2 or Python 3 is used, and `none'
107 suppresses the output completely. The default is `normal'.""") 107 suppresses the output completely. The default is `normal'.""")
108 gp.add_argument( 108 gp.add_argument(
109 "--grouping-separator", action="store", dest="grouping_separator",
110 metavar="GROUPING-SEPARATOR",
111 help="""
112 Use the given GROUPING-SEPARATOR as thousands separator.
113 Use an empty GROUPING-SEPARATOR to disable grouping.
114 The effective default depends on the --output-style: for tagged output
115 it is the underscore `_', for tabbed output it is the dot `.'.
116
117 """)
118 gp.add_argument(
109 "--half", "-H", action=SymlinkAction, dest="follow_symlinks", 119 "--half", "-H", action=SymlinkAction, dest="follow_symlinks",
110 const=FollowSymlinkConfig(True, False, False), 120 const=FollowSymlinkConfig(True, False, False),
111 help="""Follow symbolic links given on the command line but do 121 help="""Follow symbolic links given on the command line but do
112 not follow symlinks while traversing the directory tree. 122 not follow symlinks while traversing the directory tree.
113 Overwrites any other symlink related options 123 Overwrites any other symlink related options
199 the size is not printed also.""") 209 the size is not printed also.""")
200 gp.add_argument( 210 gp.add_argument(
201 "--size-only", action="store_true", 211 "--size-only", action="store_true",
202 help="""Print only the size of files and for each directory its 212 help="""Print only the size of files and for each directory its
203 accumulated directory size. Digests are not computed.""") 213 accumulated directory size. Digests are not computed.""")
214 gp.add_argument(
215 "--size-width", action="store", type=int, metavar="SIZE-WIDTH",
216 dest="size_column_width", default=15,
217 help="""Some output styles print the a filesize right-aligned
218 in a column. SIZE-WIDTH is the (minimum) width to be used. The width includes
219 grouping separators. Use 0 if no alignment should be done. Default is 15.""")
204 gp.add_argument( 220 gp.add_argument(
205 "--utf8", "--utf-8", action="store_true", 221 "--utf8", "--utf-8", action="store_true",
206 help="""Encode all file paths using UTF-8 instead of 222 help="""Encode all file paths using UTF-8 instead of
207 the filesystem encoding. Add some error tag into the path if it cannot 223 the filesystem encoding. Add some error tag into the path if it cannot
208 representated in Unicode cleanly.""") 224 representated in Unicode cleanly.""")
429 comment=[], 445 comment=[],
430 fnmatch_filters=[], 446 fnmatch_filters=[],
431 follow_symlinks=FollowSymlinkConfig(False, False, False), 447 follow_symlinks=FollowSymlinkConfig(False, False, False),
432 full_mode=False, 448 full_mode=False,
433 generator="normal", 449 generator="normal",
450 grouping_separator=None, # the output writer selects
434 logical=None, 451 logical=None,
435 minimal=None, 452 minimal=None,
436 mode=False, 453 mode=False,
437 mmap=None, 454 mmap=None,
438 mtime=False, 455 mtime=False,
439 output=None, 456 output=None,
440 output_style="tagged", 457 output_style="tagged",
441 print_size=False, 458 print_size=False,
442 size_only=False, 459 size_only=False,
460 size_column_width=15,
443 utf8=False): 461 utf8=False):
444 if not isinstance(follow_symlinks, FollowSymlinkConfig): 462 if not isinstance(follow_symlinks, FollowSymlinkConfig):
445 raise TypeError("`follow_symlinks' must be a FollowSymlinkConfig") 463 raise TypeError("`follow_symlinks' must be a FollowSymlinkConfig")
446 if not isinstance(fnmatch_filters, (list, tuple, type(None))): 464 if not isinstance(fnmatch_filters, (list, tuple, type(None))):
447 raise TypeError("`fnmatch_filters' must be a sequence (list, tuple)") 465 raise TypeError("`fnmatch_filters' must be a sequence (list, tuple)")
474 base64=base64, 492 base64=base64,
475 comment=comment, 493 comment=comment,
476 fnmatch_filters=fnmatch_filters, 494 fnmatch_filters=fnmatch_filters,
477 follow_symlinks=follow_symlinks, 495 follow_symlinks=follow_symlinks,
478 generator=generator, 496 generator=generator,
497 grouping_separator=grouping_separator,
479 logical=logical, 498 logical=logical,
480 minimal=minimal, 499 minimal=minimal,
481 mmap=mmap, 500 mmap=mmap,
482 metadata_full_mode=full_mode, 501 metadata_full_mode=full_mode,
483 metadata_mode=mode, 502 metadata_mode=mode,
484 metadata_mtime=mtime, 503 metadata_mtime=mtime,
485 output=output, 504 output=output,
486 output_style=output_style, 505 output_style=output_style,
487 print_size=print_size, 506 print_size=print_size,
488 size_only=size_only, 507 size_only=size_only,
508 size_column_width=size_column_width,
489 utf8=utf8) 509 utf8=utf8)
490 return opts 510 return opts
491 511
492 512
493 def gen_info_opts(digest_files=[], last=False): 513 def gen_info_opts(digest_files=[], last=False):
537 writerstyle = TabularTreesumWriter 557 writerstyle = TabularTreesumWriter
538 else: 558 else:
539 raise NotImplementedError("`output_style'") 559 raise NotImplementedError("`output_style'")
540 560
541 with out_cm as outfp: 561 with out_cm as outfp:
542 writer = writerstyle(outfp, use_base64=opts.base64) 562 writer = writerstyle(outfp,
563 use_base64=opts.base64,
564 grouping_separator=opts.grouping_separator
565 )
543 for d in opts.directories: 566 for d in opts.directories:
544 V1DirectoryTreesumGenerator( 567 V1DirectoryTreesumGenerator(
545 opts.algorithm, opts.mmap, 568 opts.algorithm, opts.mmap,
546 opts.follow_symlinks, 569 opts.follow_symlinks,
547 opts.generator, 570 opts.generator,
1291 1314
1292 LS = util.b(os.linesep) 1315 LS = util.b(os.linesep)
1293 """Because we write the output as binary files we need the official line 1316 """Because we write the output as binary files we need the official line
1294 separator for you OS as bytes""" 1317 separator for you OS as bytes"""
1295 1318
1296 def __init__(self, outfp, use_base64=False): 1319 DEFAULT_GROUPING_SEPARATOR = ""
1320 """Disable the thousands separator in case no subclass redefines it"""
1321
1322 def __init__(self, outfp, use_base64=False, grouping_separator=None,
1323 size_column_width=None):
1297 self._outfp = outfp 1324 self._outfp = outfp
1298 self.use_base64 = use_base64 1325 self.use_base64 = use_base64
1326 self.grouping_separator = (grouping_separator
1327 if grouping_separator is not None
1328 else self.DEFAULT_GROUPING_SEPARATOR)
1329 self.size_column_width = size_column_width or 0
1299 self.reset_crc() 1330 self.reset_crc()
1300 1331
1301 @property 1332 @property
1302 def crc(self): 1333 def crc(self):
1303 return self._crc 1334 return self._crc
1336 1367
1337 Provides high-level methods to write data lines. 1368 Provides high-level methods to write data lines.
1338 1369
1339 """ 1370 """
1340 1371
1372 DEFAULT_GROUPING_SEPARATOR = '_'
1373 """The default thousands separator"""
1374
1341 def __init__(self, outfp, **kwds): 1375 def __init__(self, outfp, **kwds):
1376 # No alignment for the size here
1377 kwds["size_column_width"] = 0
1342 super(TaggedTreesumWriter, self).__init__(outfp, **kwds) 1378 super(TaggedTreesumWriter, self).__init__(outfp, **kwds)
1343 1379
1344 def start(self, version): 1380 def start(self, version):
1345 """Begin a new block, reset the current CRC and write the VERSION 1381 """Begin a new block, reset the current CRC and write the VERSION
1346 tag. 1382 tag.
1449 GNU digest files. 1485 GNU digest files.
1450 1486
1451 Provides high-level methods to write data lines. 1487 Provides high-level methods to write data lines.
1452 1488
1453 """ 1489 """
1490
1491 DEFAULT_GROUPING_SEPARATOR = '.'
1492 """The default thousands separator"""
1454 1493
1455 def __init__(self, outfp, **kwds): 1494 def __init__(self, outfp, **kwds):
1456 super(TabularTreesumWriter, self).__init__(outfp, **kwds) 1495 super(TabularTreesumWriter, self).__init__(outfp, **kwds)
1457 1496
1458 def start(self, version): 1497 def start(self, version):