scour-project / scour

Scour - An SVG Optimizer / Cleaner
Apache License 2.0
770 stars 60 forks source link

Scour used procedurally does not run #320

Open Trixx-Darthor opened 11 months ago

Trixx-Darthor commented 11 months ago

TL;DR: Scour works from terminal, but doesn't work when called procedurally.

Hey,

I tried importing scour into my script to use it procedurally and after it ran once and crashed on wrong input (accidentally passed a list instead of a string to IO), it strangely hangs when I run it ever since. I tried restarting IDE (Pycharm 2023.2.4 CE), re-installing Scorn, changing absolute paths for only filenames with changed working directory.

The problem happens exactly at the moment of calling scour.scour.start(), when the IDE just freezes and doesn't make a step into the function. When I remove the Scour call from my project, everything works smoothly, so it seems to be a problem of Scour. Weird thing is I got it to work once and it only broke after that.

Below I attach the code I use to call Scour (debugging is just my custom console output, basicaly just glorified prints with some colors):

import os
from scour.scour import start as scour, parse_args as scour_args, getInOut as scourIO
import debugging as dbg

def _scour_svg(input_path: os.PathLike,
               output_path: os.PathLike):
    options = scour_args()
    options.input_fname = input_path
    options.output_fname = output_path
    (_input, _output) = scourIO(options)
    scour(options, _input, _output)

def _get_files_from_dir() -> [os.PathLike]:
    return [fname
            for fname in os.listdir(os.getcwd())
            if os.path.splitext(fname)[1] == ".svg" and "scoured" not in fname]

def optimize_figures(figures_dir_path: os.PathLike | str) -> None:
    original_cwd = os.getcwd()
    os.chdir(figures_dir_path)
    fnames = _get_files_from_dir()
    dbg.normal(f"{len(fnames)} un-optimized svg files found")
    for count, fname in enumerate(fnames):
        out_fname = os.path.splitext(fname)[0] + '_scoured.svg'
        _scour_svg(input_path=fname,
                   output_path=out_fname)
        dbg.normal(f"File {count} / {len(fnames)} optimized.")

I then tried running scour from terminal by cd-ing to the directory and running Scour as:

scour -i chart1.svg -o chart1_scoured.svg

which worked. What do I do wrong in the procedural approach? Also, it would be practical, if you could provide some simple way to perform procedural call. I imagine I can'T be the first one to need this and blunder.

Thanks. :)

Trixx-Darthor commented 11 months ago

Alright, after some debugging and back-tracing, I found a working solution with subprocess:

def _get_files_from_dir(figures_dir_path: str) -> [os.PathLike]:
    return [os.path.join(figures_dir_path, fname)
            for fname in os.listdir(figures_dir_path)
            if os.path.splitext(fname)[1] == ".svg" and "scoured" not in fname]

def optimize_figures(figures_dir_path: os.PathLike | str) -> None:
    input_files = _get_files_from_dir(figures_dir_path)
    dbg.normal(f"{len(input_files)} un-optimized svg files found")
    for count, fname in enumerate(input_files):
        in_fname = f'{fname}'
        out_fname = f'{os.path.splitext(fname)[0]}_scoured.svg'
        run_scour_args = [f'scour', '-i', f'{in_fname}', '-o', f'{out_fname}']
        run(run_scour_args)
        dbg.normal(f"File {count} / {len(input_files)} optimized.")

For anyone stumbling upon this issue, a major pitfall was in providing the paths with spaces correctly. Still, I would like to keep this issue open as providing some simple interface for procedural calls would be nice.