[file_utils] dirpacker: refactoring (class Bin)

This commit is contained in:
Matteo Cypriani 2014-05-31 18:57:00 -04:00
parent 61e115c4b9
commit 83e5bfddeb
1 changed files with 58 additions and 15 deletions

View File

@ -36,6 +36,29 @@ from collections import defaultdict
import math import math
class Bin:
""" Represents a bin (a volume) containing files and directories.
"""
def __init__(self, bin_id, total_size, files):
"""bin_id is the bin's identifier, total_size the sum of the sizes of
all the files it contains, and files is a dictionary with file names
as the keys and sizes as values.
"""
self.id = bin_id
self.size = total_size
self.files = files
def print(self):
"""Displays the contents of the bin.
"""
print("\n### Bin #{} ###\n# List of files:".format(self.id))
for filename, size in sorted(self.files.items()):
print("{} # {:.2f} MiB".format(filename, size))
print("# This bin's size: {:.2f} MiB".format(self.size))
sizefree = options.maxbinsize - self.size
print("# Free space: {:.2f} MiB".format(sizefree))
def du(basepath): def du(basepath):
""" Returns the size of the file of directory `basepath`, in MiB. """ Returns the size of the file of directory `basepath`, in MiB.
""" """
@ -51,10 +74,10 @@ def du(basepath):
def create_bin(binnumber): def create_bin(binnumber):
"""Creates a bin numbered `binnumber` from the global list of files and """Creates a bin numbered `binnumber` from the global list of files and
sizes. sizes, and returns it.
""" """
print("\n### Bin #{} ###\n# List of files:".format(binnumber))
binsize = 0 binsize = 0
files = {}
for size in reversed(sorted(sizes.keys())): for size in reversed(sorted(sizes.keys())):
newbinsize = binsize + size newbinsize = binsize + size
# Try the next, smaller file if we would exceed the bin's maximum size # Try the next, smaller file if we would exceed the bin's maximum size
@ -62,8 +85,7 @@ def create_bin(binnumber):
if newbinsize > options.maxbinsize: if newbinsize > options.maxbinsize:
continue continue
filename = sizes[size].pop() files[sizes[size].pop()] = size
print("{} # {:.2f} MiB".format(filename, size))
# Delete the size from the dictionary if its last file name was just # Delete the size from the dictionary if its last file name was just
# popped: # popped:
if not len(sizes[size]): if not len(sizes[size]):
@ -71,22 +93,23 @@ def create_bin(binnumber):
binsize = newbinsize binsize = newbinsize
print("# This bin's size: {:.2f} MiB".format(binsize)) return Bin(binnumber, binsize, files)
sizefree = options.maxbinsize - binsize
print("# Free space: {:.2f} MiB".format(sizefree))
### Parse command-line arguments ### ### Parse command-line arguments ###
arg_parser = argparse.ArgumentParser( arg_parser = argparse.ArgumentParser(
description="Packs files and directories into fixed-size volumes", description="Packs files and directories into fixed-size volumes",
epilog="For more information about this program, see the README file \ epilog="For more information about this program, see the README file"
provided with the distribution.") "provided with the distribution.")
arg_parser.add_argument("-s", "--size", action="store", dest="maxbinsize", arg_parser.add_argument("-s", "--size", action="store", dest="maxbinsize",
type=float, default=703, type=float, default=703,
help="maximal size of each volume (bin), in MiB; the " help="maximal size of each volume (bin), in MiB; the "
+"default is 703 MiB, i.e. the size of a 80-minute " "default is 703 MiB, i.e. the size of a 80-minute "
+"CD-ROM") "CD-ROM")
arg_parser.add_argument("-a", "--action", action="store", default="list",
help='action to be taken; can be "list" (default)'
' or "move" (move input to per-volume directories)')
arg_parser.add_argument("filenames", metavar="file", nargs="+", arg_parser.add_argument("filenames", metavar="file", nargs="+",
help="files or directories to pack") help="files or directories to pack")
options = arg_parser.parse_args() options = arg_parser.parse_args()
@ -115,14 +138,16 @@ print("# Total size of the input files: {:.2f} MiB".format(totalsize))
minbins = math.ceil(totalsize / options.maxbinsize) minbins = math.ceil(totalsize / options.maxbinsize)
print("# Minimal (optimal) number of bins required: ", minbins) print("# Minimal (optimal) number of bins required: ", minbins)
sizefree = minbins * options.maxbinsize - totalsize sizefree = minbins * options.maxbinsize - totalsize
print("# Total unused space with {} bins: {:.2f} MiB".format(minbins, sizefree)) print("# Theoretical unused space with {} bins: {:.2f} MiB"
.format(minbins, sizefree))
### Assemble the bins ### ### Assemble the bins ###
bins = []
binnumber = 1 binnumber = 1
while len(sizes): while len(sizes):
create_bin(binnumber) bins.append(create_bin(binnumber))
binnumber += 1 binnumber += 1
binscreated = binnumber - 1 binscreated = binnumber - 1
@ -130,8 +155,26 @@ binscreated = binnumber - 1
### Final statistics ### ### Final statistics ###
sizefree = binscreated * options.maxbinsize - totalsize sizefree = binscreated * options.maxbinsize - totalsize
print("\n# Total unused space over the {} bins created: {:.2f} MiB" print("""\
.format(binscreated, sizefree)) # {} bins created.
# Actual unused space over the {} bins created: {:.2f} MiB"""
.format(binscreated, binscreated, sizefree))
### Execute the requested action ###
if options.action == "list":
for b in bins:
b.print()
elif options.action == "move":
print('Action "move" is not implemented yet.')
exit(0)
else:
print('ERROR! Action "{}" is unknown.'.format(options.action))
exit(1)
### Wrapping-up ###
if (ignored_files): if (ignored_files):
print("\n# WARNING! There were ignored files, see at the top of this log.") print("\n# WARNING! There were ignored files, see at the top of this log.")