add progress bar
This commit is contained in:
parent
846e7cc4b4
commit
1144dae60b
1
Makefile
1
Makefile
@ -22,6 +22,7 @@ check: format lint check-type
|
|||||||
|
|
||||||
build: check
|
build: check
|
||||||
@rm -rf dist/*
|
@rm -rf dist/*
|
||||||
|
$(PYTHON) build-deps.py
|
||||||
$(PYTHON) -m hatch -v build -t wheel
|
$(PYTHON) -m hatch -v build -t wheel
|
||||||
|
|
||||||
install: build
|
install: build
|
||||||
|
|||||||
47
build-deps.py
Normal file
47
build-deps.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
DEPS_REGEX = "dependencies = \[[^\]]*\]"
|
||||||
|
PYPROJECT_FILENAME = "pyproject.toml"
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
"""
|
||||||
|
build-deps retrieves all mandatory requirements in `requirements.txt`
|
||||||
|
and copies them in `pyproject.toml` dependencies list.
|
||||||
|
"""
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("-d", "--dry-run", action="store_true")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# read and store requirements
|
||||||
|
requirements: list[str] = []
|
||||||
|
with open("requirements.txt", "r") as f:
|
||||||
|
for d in f.readlines():
|
||||||
|
d = d.replace("\n", "")
|
||||||
|
requirements.append(f'"{d}"')
|
||||||
|
|
||||||
|
# format requirements for pryproject.toml
|
||||||
|
deps: str = "dependencies = ["
|
||||||
|
deps += "\n" if len(requirements) >= 1 else ""
|
||||||
|
for dep in requirements:
|
||||||
|
deps += f"\t{dep},\n"
|
||||||
|
deps += "]"
|
||||||
|
|
||||||
|
# get and replace the pyproject.toml content
|
||||||
|
content: str = ""
|
||||||
|
with open(PYPROJECT_FILENAME, "r") as f:
|
||||||
|
content = f.read()
|
||||||
|
content = re.sub(DEPS_REGEX, deps, content, 1)
|
||||||
|
|
||||||
|
# write the new content in a temp file
|
||||||
|
with open(f"{PYPROJECT_FILENAME}.tmp", "w") as f:
|
||||||
|
f.write(content)
|
||||||
|
|
||||||
|
# if not dry run, override the original pyproject.toml
|
||||||
|
if not args.dry_run:
|
||||||
|
try:
|
||||||
|
os.rename(f"{PYPROJECT_FILENAME}.tmp", PYPROJECT_FILENAME)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"error occurred while overriding pyproject file: {e}")
|
||||||
|
os.remove(f"{PYPROJECT_FILENAME}.tmp")
|
||||||
@ -6,7 +6,9 @@ build-backend = "hatchling.build"
|
|||||||
name = "optimg"
|
name = "optimg"
|
||||||
dynamic = ["version"]
|
dynamic = ["version"]
|
||||||
description = "Optimize JPEG and PNG files from a directory."
|
description = "Optimize JPEG and PNG files from a directory."
|
||||||
dependencies = []
|
dependencies = [
|
||||||
|
"tqdm==4.67.1",
|
||||||
|
]
|
||||||
|
|
||||||
[project.scripts]
|
[project.scripts]
|
||||||
optimg = "optimg.__main__:main"
|
optimg = "optimg.__main__:main"
|
||||||
|
|||||||
1
requirements.txt
Normal file
1
requirements.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
tqdm==4.67.1
|
||||||
@ -113,7 +113,7 @@ def main():
|
|||||||
try:
|
try:
|
||||||
result = optimizer.optimize(fg)
|
result = optimizer.optimize(fg)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
logging.info("optimizer stopped gracefully")
|
logging.error("oops, you stopped the optimizer abrutly...")
|
||||||
exit(0)
|
exit(0)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.fatal(
|
logging.fatal(
|
||||||
|
|||||||
@ -3,10 +3,12 @@ import os
|
|||||||
import signal
|
import signal
|
||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
from concurrent.futures import ProcessPoolExecutor
|
from concurrent.futures import ProcessPoolExecutor, as_completed
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
from tqdm import tqdm
|
||||||
|
|
||||||
from .files import File, FileGroup, FileImgMimetype
|
from .files import File, FileGroup, FileImgMimetype
|
||||||
|
|
||||||
__all__ = ["ImgOptimizer", "OptimizerResult"]
|
__all__ = ["ImgOptimizer", "OptimizerResult"]
|
||||||
@ -33,7 +35,7 @@ def _jpeg_optim(dest_dir: str, file: File) -> tuple["File", Optional["File"]] |
|
|||||||
try:
|
try:
|
||||||
_ = subprocess.run(cmd, shell=True, check=True)
|
_ = subprocess.run(cmd, shell=True, check=True)
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
logging.error("error while running command: %s, err: %s", cmd, e.output)
|
logging.error("error while running command: %s, err: %s", cmd, e.stderr or "?")
|
||||||
return None
|
return None
|
||||||
except Exception:
|
except Exception:
|
||||||
logging.error("unexpected error while running command: %s", cmd, exc_info=True)
|
logging.error("unexpected error while running command: %s", cmd, exc_info=True)
|
||||||
@ -130,20 +132,22 @@ class ImgOptimizer:
|
|||||||
p.submit(_optim, self.dest_dir, f) for f in file_group.get_files()
|
p.submit(_optim, self.dest_dir, f) for f in file_group.get_files()
|
||||||
]
|
]
|
||||||
|
|
||||||
file_group_optim = FileGroup()
|
file_group_optim = FileGroup()
|
||||||
optimized = 0
|
optimized = 0
|
||||||
for f in futures:
|
for f in tqdm(
|
||||||
if (res := f.result()) and res is not None:
|
as_completed(futures), total=len(futures), desc="Optimizing..."
|
||||||
match res:
|
):
|
||||||
case (orig, None):
|
if (res := f.result()) and res is not None:
|
||||||
logging.debug(f"no optimization for file: {orig}")
|
match res:
|
||||||
file_group_optim.add(orig)
|
case (orig, None):
|
||||||
case (orig, opti):
|
logging.debug(f"no optimization for file: {orig}")
|
||||||
optimized += 1
|
file_group_optim.add(orig)
|
||||||
logging.debug(
|
case (orig, opti):
|
||||||
f"optimization for file: {orig} -> {(1 - (opti.size / orig.size)) * 100:.2f}%" # noqa
|
optimized += 1
|
||||||
)
|
logging.debug(
|
||||||
file_group_optim.add(opti)
|
f"optimization for file: {orig} -> {(1 - (opti.size / orig.size)) * 100:.2f}%" # noqa
|
||||||
|
)
|
||||||
|
file_group_optim.add(opti)
|
||||||
|
|
||||||
logging.info(f"optimization finished in {time.perf_counter() - start:.2f}s")
|
logging.info(f"optimization finished in {time.perf_counter() - start:.2f}s")
|
||||||
return OptimizerResult(file_group, file_group_optim, optimized)
|
return OptimizerResult(file_group, file_group_optim, optimized)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user