Coverage for pyguymer3/image/optipng.py: 86%

14 statements  

« prev     ^ index     » next       coverage.py v7.9.2, created at 2025-07-08 18:47 +0000

1#!/usr/bin/env python3 

2 

3# Define function ... 

4def optipng( 

5 fname, 

6 /, 

7 *, 

8 optipngPath = None, 

9 pool = None, 

10 timeout = 60.0, 

11): 

12 """ 

13 "optipng" does not modify, and it does not touch, the image even if it 

14 cannot make it smaller, therefore it is safe to keep on running "optipng" on 

15 the same PNG over and over again. 

16 """ 

17 

18 # Import standard modules ... 

19 import multiprocessing 

20 import multiprocessing.pool 

21 import os 

22 import shutil 

23 import subprocess 

24 

25 # ************************************************************************** 

26 

27 # Try to find the paths if the user did not provide them ... 

28 if optipngPath is None: 

29 optipngPath = shutil.which("optipng") 

30 assert optipngPath is not None, "\"optipng\" is not installed" 

31 

32 # Check that the image exists ... 

33 if not os.path.exists(fname): 

34 raise Exception(f"\"{fname}\" does not exist") from None 

35 

36 # Check if the user wants to be asynchronous ... 

37 if isinstance(pool, multiprocessing.pool.Pool): 

38 # Optimise PNG asynchronously ... 

39 # NOTE: I have to use the "--" argument to "optipng" in case the user 

40 # supplies a file name which starts with "-". 

41 pool.apply_async( 

42 subprocess.run, 

43 [ 

44 [ 

45 optipngPath, 

46 "-strip", "all", 

47 "--", 

48 fname, 

49 ] 

50 ], 

51 { 

52 "check" : True, 

53 "encoding" : "utf-8", 

54 "stderr" : subprocess.DEVNULL, 

55 "stdout" : subprocess.DEVNULL, 

56 "timeout" : timeout, 

57 }, 

58 ) 

59 else: 

60 # Optimise PNG synchronously ... 

61 # NOTE: I have to use the "--" argument to "optipng" in case the user 

62 # supplies a file name which starts with "-". 

63 subprocess.run( 

64 [ 

65 optipngPath, 

66 "-strip", "all", 

67 "--", 

68 fname, 

69 ], 

70 check = True, 

71 encoding = "utf-8", 

72 stderr = subprocess.DEVNULL, 

73 stdout = subprocess.DEVNULL, 

74 timeout = timeout, 

75 )