Reorganized the way I do these args, kwargs, and script building.
This commit is contained in:
parent
98c59bce13
commit
31b8047381
1 changed files with 80 additions and 86 deletions
166
rarpar.py
166
rarpar.py
|
|
@ -11,6 +11,7 @@ from voussoirkit import betterhelp
|
||||||
from voussoirkit import bytestring
|
from voussoirkit import bytestring
|
||||||
from voussoirkit import operatornotify
|
from voussoirkit import operatornotify
|
||||||
from voussoirkit import pathclass
|
from voussoirkit import pathclass
|
||||||
|
from voussoirkit import pipeable
|
||||||
from voussoirkit import subproctools
|
from voussoirkit import subproctools
|
||||||
from voussoirkit import vlogging
|
from voussoirkit import vlogging
|
||||||
from voussoirkit import winglob
|
from voussoirkit import winglob
|
||||||
|
|
@ -26,6 +27,9 @@ RESERVE_SPACE_ON_DRIVE = 5 * bytestring.GIBIBYTE
|
||||||
COMPRESSION_STORE = 0
|
COMPRESSION_STORE = 0
|
||||||
COMPRESSION_MAX = 5
|
COMPRESSION_MAX = 5
|
||||||
|
|
||||||
|
DATE_STRFTIME = '%Y-%m-%d'
|
||||||
|
DATETIME_STRFTIME = '%Y-%m-%d_%H-%M-%S'
|
||||||
|
|
||||||
class RarParException(Exception):
|
class RarParException(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
@ -35,7 +39,8 @@ class RarExists(RarParException):
|
||||||
class NotEnoughSpace(RarParException):
|
class NotEnoughSpace(RarParException):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def RARCOMMAND(
|
def build_rarcommand(
|
||||||
|
*,
|
||||||
path,
|
path,
|
||||||
basename,
|
basename,
|
||||||
workdir,
|
workdir,
|
||||||
|
|
@ -49,6 +54,8 @@ def RARCOMMAND(
|
||||||
volume=None,
|
volume=None,
|
||||||
):
|
):
|
||||||
'''
|
'''
|
||||||
|
winrar [options] destination files_to_include
|
||||||
|
----------------------------------------------------------------------------
|
||||||
winrar
|
winrar
|
||||||
a = make archive
|
a = make archive
|
||||||
-cp{profile} = use compression profile. this must come first so that
|
-cp{profile} = use compression profile. this must come first so that
|
||||||
|
|
@ -74,8 +81,8 @@ def RARCOMMAND(
|
||||||
-x = exclude certain filenames
|
-x = exclude certain filenames
|
||||||
destination
|
destination
|
||||||
workdir/basename.rar
|
workdir/basename.rar
|
||||||
files to include
|
files_to_include
|
||||||
input_pattern
|
glob pattern
|
||||||
'''
|
'''
|
||||||
command = [WINRAR, 'a']
|
command = [WINRAR, 'a']
|
||||||
|
|
||||||
|
|
@ -125,14 +132,30 @@ def RARCOMMAND(
|
||||||
|
|
||||||
return command
|
return command
|
||||||
|
|
||||||
def PARCOMMAND(workdir, basename, par):
|
def run_rar(**kwargs) -> list:
|
||||||
'''
|
'''
|
||||||
|
Run the winrar command and return a list of rar and rev files.
|
||||||
|
'''
|
||||||
|
workdir = kwargs['workdir']
|
||||||
|
basename = kwargs['basename']
|
||||||
|
command = build_rarcommand(**kwargs)
|
||||||
|
creationflags = subprocess.CREATE_NO_WINDOW if sys.stdout is None else 0
|
||||||
|
log.info(subproctools.format_command(command))
|
||||||
|
status = subprocess.run(command, creationflags=creationflags).returncode
|
||||||
|
return (workdir.glob_files(f'{basename}*.rar') + workdir.glob_files(f'{basename}*.rev'))
|
||||||
|
|
||||||
|
def build_parcommand(workdir, basename, par):
|
||||||
|
'''
|
||||||
|
phpar2 [options] destination files_to_include
|
||||||
|
----------------------------------------------------------------------------
|
||||||
phpar2
|
phpar2
|
||||||
c = create pars
|
c = create pars
|
||||||
-t1 = thread count: 1
|
-t1 = thread count: 1
|
||||||
-r{x} = x% recovery
|
-r{x} = x% recovery
|
||||||
destination
|
destination
|
||||||
workdir/basename.par2
|
workdir/basename.par2
|
||||||
|
files_to_include
|
||||||
|
glob pattern
|
||||||
'''
|
'''
|
||||||
command = [
|
command = [
|
||||||
PAR2,
|
PAR2,
|
||||||
|
|
@ -144,6 +167,18 @@ def PARCOMMAND(workdir, basename, par):
|
||||||
]
|
]
|
||||||
return command
|
return command
|
||||||
|
|
||||||
|
def run_par(**kwargs) -> list:
|
||||||
|
'''
|
||||||
|
Run the par command and return a list of par2 files.
|
||||||
|
'''
|
||||||
|
workdir = kwargs['workdir']
|
||||||
|
basename = kwargs['basename']
|
||||||
|
command = build_parcommand(**kwargs)
|
||||||
|
creationflags = subprocess.CREATE_NO_WINDOW if sys.stdout is None else 0
|
||||||
|
log.info(subproctools.format_command(command))
|
||||||
|
status = subprocess.run(command, creationflags=creationflags).returncode
|
||||||
|
return workdir.glob_files(f'{basename}*.par2')
|
||||||
|
|
||||||
def assert_enough_space(path, size, rec, rev, par):
|
def assert_enough_space(path, size, rec, rev, par):
|
||||||
plus_percent = (rec + rev + par) / 100
|
plus_percent = (rec + rev + par) / 100
|
||||||
needed = size * (1 + plus_percent)
|
needed = size * (1 + plus_percent)
|
||||||
|
|
@ -152,12 +187,6 @@ def assert_enough_space(path, size, rec, rev, par):
|
||||||
|
|
||||||
path.assert_disk_space(reserve)
|
path.assert_disk_space(reserve)
|
||||||
|
|
||||||
def move(pattern, directory):
|
|
||||||
files = winglob.glob(pattern)
|
|
||||||
for file in files:
|
|
||||||
print(file)
|
|
||||||
shutil.move(file, directory)
|
|
||||||
|
|
||||||
def normalize_compression(compression):
|
def normalize_compression(compression):
|
||||||
if compression is None:
|
if compression is None:
|
||||||
return None
|
return None
|
||||||
|
|
@ -283,41 +312,6 @@ def normalize_volume(volume, pathsize):
|
||||||
raise ValueError('Volume must be >= 1.')
|
raise ValueError('Volume must be >= 1.')
|
||||||
return volume
|
return volume
|
||||||
|
|
||||||
def run_script(script, dry=False):
|
|
||||||
'''
|
|
||||||
`script` can be a list of strings, which are command line commands, or
|
|
||||||
callable Python functions. They will be run in order, and the sequence
|
|
||||||
will terminate if any step returns a bad status code. Your Python functions
|
|
||||||
must return either 0 or None to be considered successful, all other return
|
|
||||||
values will be considered failures.
|
|
||||||
'''
|
|
||||||
status = 0
|
|
||||||
|
|
||||||
for command in script:
|
|
||||||
if isinstance(command, str):
|
|
||||||
log.info(command)
|
|
||||||
elif isinstance(command, list):
|
|
||||||
log.info(subproctools.format_command(command))
|
|
||||||
else:
|
|
||||||
log.info(command)
|
|
||||||
|
|
||||||
if dry:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if isinstance(command, str):
|
|
||||||
status = os.system(command)
|
|
||||||
elif isinstance(command, list):
|
|
||||||
# sys.stdout is None indicates pythonw.
|
|
||||||
creationflags = subprocess.CREATE_NO_WINDOW if sys.stdout is None else 0
|
|
||||||
status = subprocess.run(command, creationflags=creationflags).returncode
|
|
||||||
else:
|
|
||||||
status = command()
|
|
||||||
if status not in [0, None]:
|
|
||||||
log.error('!!!! error status: %s', status)
|
|
||||||
break
|
|
||||||
|
|
||||||
return status
|
|
||||||
|
|
||||||
def rarpar(
|
def rarpar(
|
||||||
path,
|
path,
|
||||||
*,
|
*,
|
||||||
|
|
@ -382,8 +376,8 @@ def rarpar(
|
||||||
par=par or 0,
|
par=par or 0,
|
||||||
)
|
)
|
||||||
|
|
||||||
date = time.strftime('%Y-%m-%d')
|
date = time.strftime(DATE_STRFTIME)
|
||||||
timestamp = time.strftime('%Y-%m-%d_%H-%M-%S')
|
timestamp = time.strftime(DATETIME_STRFTIME)
|
||||||
|
|
||||||
if basename is not None:
|
if basename is not None:
|
||||||
basename = re.sub(r'\.rar$', '', basename)
|
basename = re.sub(r'\.rar$', '', basename)
|
||||||
|
|
@ -402,11 +396,11 @@ def rarpar(
|
||||||
if existing:
|
if existing:
|
||||||
raise RarExists(f'{existing[0].absolute_path} already exists.')
|
raise RarExists(f'{existing[0].absolute_path} already exists.')
|
||||||
|
|
||||||
# Script building ##############################################################################
|
output_files = []
|
||||||
|
|
||||||
script = []
|
################################################################################################
|
||||||
|
|
||||||
rarcommand = RARCOMMAND(
|
rar_kwargs = dict(
|
||||||
path=path,
|
path=path,
|
||||||
basename=basename,
|
basename=basename,
|
||||||
compression=compression,
|
compression=compression,
|
||||||
|
|
@ -419,51 +413,50 @@ def rarpar(
|
||||||
volume=volume,
|
volume=volume,
|
||||||
workdir=workdir,
|
workdir=workdir,
|
||||||
)
|
)
|
||||||
script.append(rarcommand)
|
if dry:
|
||||||
|
rarcommand = build_rarcommand(**rar_kwargs)
|
||||||
|
log.info(subproctools.format_command(rarcommand))
|
||||||
|
else:
|
||||||
|
rar_files = run_rar(**rar_kwargs)
|
||||||
|
output_files.extend(rar_files)
|
||||||
|
|
||||||
if par:
|
################################################################################################
|
||||||
parcommand = PARCOMMAND(
|
|
||||||
basename=basename,
|
|
||||||
par=par,
|
|
||||||
workdir=workdir,
|
|
||||||
)
|
|
||||||
script.append(parcommand)
|
|
||||||
|
|
||||||
def move_rars():
|
par_kwargs = dict(
|
||||||
move(f'{workdir.absolute_path}\\{basename}*.rar', f'{moveto.absolute_path}')
|
basename=basename,
|
||||||
|
par=par,
|
||||||
|
workdir=workdir,
|
||||||
|
)
|
||||||
|
if not par:
|
||||||
|
pass
|
||||||
|
elif dry:
|
||||||
|
parcommand = build_parcommand(**par_kwargs)
|
||||||
|
log.info(subproctools.format_command(parcommand))
|
||||||
|
else:
|
||||||
|
par_files = run_par(**par_kwargs)
|
||||||
|
output_files.extend(par_files)
|
||||||
|
|
||||||
def move_revs():
|
################################################################################################
|
||||||
move(f'{workdir.absolute_path}\\{basename}*.rev', f'{moveto.absolute_path}')
|
|
||||||
|
|
||||||
def move_pars():
|
if moveto and not dry:
|
||||||
move(f'{workdir.absolute_path}\\{basename}*.par2', f'{moveto.absolute_path}')
|
moved_files = []
|
||||||
|
for file in output_files:
|
||||||
|
shutil.move(file.absolute_path, moveto.absolute_path)
|
||||||
|
moved_files.append(moveto.with_child(file.basename))
|
||||||
|
output_files = moved_files
|
||||||
|
|
||||||
if moveto:
|
if recycle_original and not dry:
|
||||||
if True:
|
|
||||||
script.append(move_rars)
|
|
||||||
if rev:
|
|
||||||
script.append(move_revs)
|
|
||||||
if par:
|
|
||||||
script.append(move_pars)
|
|
||||||
|
|
||||||
def recycle():
|
|
||||||
send2trash.send2trash(path.absolute_path)
|
send2trash.send2trash(path.absolute_path)
|
||||||
|
|
||||||
if recycle_original:
|
return output_files
|
||||||
script.append(recycle)
|
|
||||||
|
|
||||||
#### ####
|
|
||||||
|
|
||||||
status = run_script(script, dry)
|
|
||||||
|
|
||||||
return status
|
|
||||||
|
|
||||||
|
####################################################################################################
|
||||||
# COMMAND LINE #####################################################################################
|
# COMMAND LINE #####################################################################################
|
||||||
|
####################################################################################################
|
||||||
|
|
||||||
def rarpar_argparse(args):
|
def rarpar_argparse(args):
|
||||||
status = 0
|
|
||||||
try:
|
try:
|
||||||
return rarpar(
|
output_files = rarpar(
|
||||||
path=args.path,
|
path=args.path,
|
||||||
volume=args.volume,
|
volume=args.volume,
|
||||||
basename=args.basename,
|
basename=args.basename,
|
||||||
|
|
@ -480,11 +473,12 @@ def rarpar_argparse(args):
|
||||||
solid=args.solid,
|
solid=args.solid,
|
||||||
workdir=args.workdir,
|
workdir=args.workdir,
|
||||||
)
|
)
|
||||||
|
for file in output_files:
|
||||||
|
pipeable.stdout(file.absolute_path)
|
||||||
|
return 0
|
||||||
except (RarExists, pathclass.NotEnoughSpace) as exc:
|
except (RarExists, pathclass.NotEnoughSpace) as exc:
|
||||||
log.fatal(exc)
|
log.fatal(exc)
|
||||||
status = 1
|
return 1
|
||||||
|
|
||||||
return status
|
|
||||||
|
|
||||||
@operatornotify.main_decorator(subject='rarpar.py')
|
@operatornotify.main_decorator(subject='rarpar.py')
|
||||||
@vlogging.main_decorator
|
@vlogging.main_decorator
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue