Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python source formatting updates #99

Merged
merged 5 commits into from
Jun 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ test-coverage:

test-python:
tox
flake8 --ignore=E501,W503,E121,E123,E126,E226,E24,E704,W503,W504,N806 src/crunch.py
flake8 src/crunch.py

test-shell:
shellcheck --exclude=2046 src/*.sh
Expand Down
2 changes: 2 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[flake8]
max-line-length = 90
137 changes: 55 additions & 82 deletions src/crunch.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@
Source: https://github.com/chrissimpkins/Crunch
==================================================

crunch is a command line executable that performs lossy optimization of one or more png image files with pngquant and zopflipng.
crunch is a command line executable that performs lossy optimization of one
or more png image files with pngquant and zopflipng.

Usage:
$ crunch [image path 1]...[image path n]
Expand Down Expand Up @@ -95,8 +96,8 @@ def main(argv):

if len(argv) == 0:
sys.stderr.write(
ERROR_STRING + " Please include one or more paths to PNG image files as "
"arguments to the script." + os.linesep
f"{ERROR_STRING} Please include one or more paths to PNG image files as "
"arguments to the script.{os.linesep}"
)
sys.exit(1)

Expand Down Expand Up @@ -138,63 +139,50 @@ def main(argv):
# Not a file test
if not os.path.isfile(png_path): # is not an existing file
sys.stderr.write(
ERROR_STRING
+ " '"
+ png_path
+ "' does not appear to be a valid path to a PNG file"
+ os.linesep
f"{ERROR_STRING} '{png_path}' does not appear to be a "
f"valid path to a PNG file{os.linesep}"
)
sys.exit(1) # not a file, abort immediately
# PNG validity test
if not is_valid_png(png_path):
sys.stderr.write(
ERROR_STRING
+ " '"
+ png_path
+ "' is not a valid PNG file."
+ os.linesep
f"{ERROR_STRING} '{png_path}' is not a valid PNG file.{os.linesep}"
)
if is_gui(argv):
log_error(png_path + " is not a valid PNG file.")
log_error(f"{png_path} is not a valid PNG file.")
NOTPNG_ERROR_FOUND = True

# Exit after checking all file requests and reporting on all invalid file paths (above)
# Exit after checking all file requests and reporting on all invalid
# file paths (above)
if NOTPNG_ERROR_FOUND is True:
sys.stderr.write(
"The request was not executed successfully. Please try again with one or more valid PNG files."
+ os.linesep
f"The request was not executed successfully. Please try again "
f"with one or more valid PNG files.{os.linesep}"
)
if is_gui(argv):
log_error(
"The request was not executed successfully. Please try again with one or more valid PNG files."
"The request was not executed successfully. Please try "
"again with one or more valid PNG files."
)
sys.exit(1)

# Dependency error handling
if not os.path.exists(PNGQUANT_EXE_PATH):
sys.stderr.write(
ERROR_STRING
+ " pngquant executable was not identified on path '"
+ PNGQUANT_EXE_PATH
+ "'"
+ os.linesep
f"{ERROR_STRING} pngquant executable was not identified on path "
f"'{PNGQUANT_EXE_PATH}'{os.linesep}"
)
if is_gui(argv):
log_error(
"pngquant was not found on the expected path " + PNGQUANT_EXE_PATH
)
log_error(f"pngquant was not found on the expected path {PNGQUANT_EXE_PATH}")
sys.exit(1)
elif not os.path.exists(ZOPFLIPNG_EXE_PATH):
sys.stderr.write(
ERROR_STRING
+ " zopflipng executable was not identified on path '"
+ ZOPFLIPNG_EXE_PATH
+ "'"
+ os.linesep
f"{ERROR_STRING} zopflipng executable was not identified on path "
f"'{ZOPFLIPNG_EXE_PATH}'{os.linesep}"
)
if is_gui(argv):
log_error(
"zopflipng was not found on the expected path " + ZOPFLIPNG_EXE_PATH
f"zopflipng was not found on the expected path {ZOPFLIPNG_EXE_PATH}"
)
sys.exit(1)

Expand All @@ -208,33 +196,31 @@ def main(argv):
optimize_png(png_path_list[0])
else:
processes = PROCESSES
# if not defined by user, start by defining spawned processes as number of available cores
# if not defined by user, start by defining spawned processes as number
# of available cores
if processes == 0:
processes = cpu_count()

# if total cores available is greater than number of files requested, limit to the latter number
# if total cores available is greater than number of files requested,
# limit to the latter number
if processes > len(png_path_list):
processes = len(png_path_list)

print(
"Spawning "
+ str(processes)
+ " processes to optimize "
+ str(len(png_path_list))
+ " image files..."
f"Spawning {processes} processes to optimize {len(png_path_list)} "
f"image files..."
)
p = Pool(processes)
try:
p.map(optimize_png, png_path_list)
except Exception as e:
stdstream_lock.acquire()
sys.stderr.write("-----" + os.linesep)
sys.stderr.write(f"-----{os.linesep}")
sys.stderr.write(
ERROR_STRING
+ " Error detected during execution of the request."
+ os.linesep
f"{ERROR_STRING} Error detected during execution of the request."
f"{os.linesep}"
)
sys.stderr.write(str(e) + os.linesep)
sys.stderr.write(f"{e}{os.linesep}")
stdstream_lock.release()
if is_gui(argv):
log_error(str(e))
Expand Down Expand Up @@ -272,49 +258,40 @@ def optimize_png(png_path):
pngquant_options = (
" --quality=80-98 --skip-if-larger --force --strip --speed 1 --ext -crunch.png "
)
pngquant_command = (
PNGQUANT_EXE_PATH + pngquant_options + shellquote(img.pre_filepath)
)
pngquant_command = PNGQUANT_EXE_PATH + pngquant_options + shellquote(img.pre_filepath)
try:
subprocess.check_output(pngquant_command, stderr=subprocess.STDOUT, shell=True)
except CalledProcessError as cpe:
if cpe.returncode == 98:
# this is the status code when file size increases with execution of pngquant.
# ignore at this stage, original file copied at beginning of zopflipng processing
# below if it is not present due to these errors
# ignore at this stage, original file copied at beginning of zopflipng
# processing below if it is not present due to these errors
pass
elif cpe.returncode == 99:
# this is the status code when the image quality falls below the set min value
# ignore at this stage, original lfile copied at beginning of zopflipng processing
# below if it is not present to these errors
# ignore at this stage, original lfile copied at beginning of zopflipng
# processing below if it is not present to these errors
pass
else:
stdstream_lock.acquire()
sys.stderr.write(
ERROR_STRING
+ " "
+ img.pre_filepath
+ " processing failed at the pngquant stage."
+ os.linesep
f"{ERROR_STRING} {img.pre_filepath} processing failed at the pngquant "
f"stage.{os.linesep}"
)
stdstream_lock.release()
if is_gui(sys.argv):
log_error(
img.pre_filepath
+ " processing failed at the pngquant stage. "
+ os.linesep
+ str(cpe)
f"{img.pre_filepath} processing failed at the pngquant stage."
f"{os.linesep}{cpe}"
)
return None
else:
raise cpe
except Exception as e:
if is_gui(sys.argv):
log_error(
img.pre_filepath
+ " processing failed at the pngquant stage. "
+ os.linesep
+ str(e)
f"{img.pre_filepath} processing failed at the pngquant stage."
f"{os.linesep}{e}"
)
return None
else:
Expand All @@ -329,9 +306,10 @@ def optimize_png(png_path):
# pngquant does not write expected file path if the file was larger after processing
if not os.path.exists(img.post_filepath):
shutil.copy(img.pre_filepath, img.post_filepath)
# If pngquant did not quantize the file, permit zopflipng to attempt compression with mulitple
# filters. This achieves better compression than the default approach for non-quantized PNG
# files, but takes significantly longer (based upon testing by CS)
# If pngquant did not quantize the file, permit zopflipng to attempt compression
# with mulitple filters. This achieves better compression than the default
# approach for non-quantized PNG files, but takes significantly longer
# (based upon testing by CS)
zopflipng_options = " -y --lossy_transparent "
zopflipng_command = (
ZOPFLIPNG_EXE_PATH
Expand All @@ -345,30 +323,23 @@ def optimize_png(png_path):
except CalledProcessError as cpe:
stdstream_lock.acquire()
sys.stderr.write(
ERROR_STRING
+ " "
+ img.pre_filepath
+ " processing failed at the zopflipng stage."
+ os.linesep
f"{ERROR_STRING} {img.pre_filepath} processing failed at the zopflipng "
f"stage.{os.linesep}"
)
stdstream_lock.release()
if is_gui(sys.argv):
log_error(
img.pre_filepath
+ " processing failed at the zopflipng stage. "
+ os.linesep
+ str(cpe)
f"{img.pre_filepath} processing failed at the zopflipng stage."
f"{os.linesep}{cpe}"
)
return None
else:
raise cpe
except Exception as e:
if is_gui(sys.argv):
log_error(
img.pre_filepath
+ " processing failed at the pngquant stage. "
+ os.linesep
+ str(e)
f"{img.pre_filepath} processing failed at the zopflipng stage."
f"{os.linesep}{e}"
)
return None
else:
Expand All @@ -383,7 +354,8 @@ def optimize_png(png_path):
if not is_gui(sys.argv) and percent < 100:
percent_string = format_ansi_green(percent_string)

# report percent original file size / post file path / size (bytes) to stdout (command line executable)
# report percent original file size / post file path / size (bytes) to
# stdout (command line executable)
stdstream_lock.acquire()
print(
"[ "
Expand All @@ -396,7 +368,8 @@ def optimize_png(png_path):
)
stdstream_lock.release()

# report percent original file size / post file path / size (bytes) to log file (macOS GUI + right-click service)
# report percent original file size / post file path / size (bytes) to log file
# (macOS GUI + right-click service)
if is_gui(sys.argv):
log_info(
"[ "
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tox]
skipsdist = True
envlist = py27,py38
envlist = py310

[testenv]
deps = pytest
Expand Down