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

Feature request: call scour from Python code #290

Open
rgoubet opened this issue Jan 31, 2022 · 8 comments
Open

Feature request: call scour from Python code #290

rgoubet opened this issue Jan 31, 2022 · 8 comments

Comments

@rgoubet
Copy link

rgoubet commented Jan 31, 2022

I'm sure it must be possible to call scour, along with the various command-line flags, within Python code, which is interesting to optimize svg files generated by a Python program. From what I can tell, the XML string is passed to the scourString function, but I can't make out how flags are passed as options.

It's probably a matter of documentation, but, IMO, it would be worth adding a note on this and not limit scour's usage to the command line.

@lfoscari
Copy link

lfoscari commented Feb 5, 2022

I think I found a way to call scour from Python code:

from scour import scour
import sys

sys.argv = ["-i", "input.svg", "-o", "output.svg"]
scour.run()

The run function uses optparse in the background, which reads the command line arguments directly.

@rgoubet
Copy link
Author

rgoubet commented Feb 6, 2022

Yes, of course you can always call the script itself, but it would be much clearer if one could use the scourString method itself.

@rgoubet
Copy link
Author

rgoubet commented Feb 8, 2022

At least, this seems to work to optimize an XML string (i.e. without a need for an SVG file on disk):

from scour import scour

def minify_svg(xml_string):
    opts = scour.sanitizeOptions(
        {
            "digits": 5,
            "quiet": False,
            "verbose": False,
            "cdigits": -1,
            "simple_colors": True,
            "style_to_xml": True,
            "group_collapse": True,
            "group_create": False,
            "keep_editor_data": False,
            "keep_defs": False,
            "renderer_workaround": True,
            "strip_xml_prolog": False,
            "remove_titles": True,
            "remove_descriptions": True,
            "remove_metadata": True,
            "remove_descriptive_elements": True,
            "strip_comments": True,
            "embed_rasters": True,
            "enable_viewboxing": True,
            "indent_type": "none",
            "indent_depth": 1,
            "newlines": True,
            "strip_xml_space_attribute": False,
            "strip_ids": True,
            "shorten_ids": True,
            "shorten_ids_prefix": "",
            "protect_ids_noninkscape": False,
            "protect_ids_list": None,
            "protect_ids_prefix": None,
            "error_on_flowtext": False,
        }
    )
    return scour.scourString(xml_string, opts)

All options in the opts dictionary are probably not necessary (I understand that the sanitizeOptions function sets the default option values), but I'd need to run trial and error with each of them to understand their meaning compared to the command line options.

@Moonbase59
Copy link

Moonbase59 commented Feb 14, 2022

Scour with an "official" module API would be nice, yes. +1
Calling it as a subprocess from another Python app feels so suboptimal…

@brettrp
Copy link

brettrp commented Apr 1, 2022

This works fine for me:

    scour_options_dict = {'strip_comments': True, 'indent_type': 'none', 'shorten_ids': True, 'enable_viewboxing': True, 'strip_ids': True, 'strip_xml_prolog': True, 'remove_metadata': True}
    scour_options = SimpleNamespace(**scour_options_dict)
    svg_compressed = scourString(svg, scour_options)

The only real problem I can see with that is that it's undocumented, and the names of the keys are not exactly the same as the names of the command line options, so in theory they could change.

@rstemmer
Copy link

I additionally imported the parse_args function.
You can give the command line arguments as list of string to that function.
The function then returns a valid options-dictionary.

from scour.scour import scourString
from scour.scour import sanitizeOptions as sanitizeScourOptions
from scour.scour import parse_args as parseScourArgs

def Optimize(sourcesvg):
    scouroptions = parseScourArgs([
        "--enable-id-stripping",
        "--enable-comment-stripping",
        "--shorten-ids",
        "--indent=none",
        "--no-line-breaks"])
    scouroptions = sanitizeScourOptions(scouroptions)
    optimizedsvg = scourString(sourcesvg, scouroptions)
    return optimizedsvg

(Source)

Of course, as long as this is not an official and documented feature to use Scour functions inside other Python tools, our code can break with any update. 😄

@mangelozzi
Copy link

Another usecase is for a web server, one especially does not want the overhead/complexity writing to disk (multiple workers) and reading from disk. You generally want to keep everything in memory, in which case an API would be great.

@mangelozzi
Copy link

I additionally imported the parse_args function. You can give the command line arguments as list of string to that function. The function then returns a valid options-dictionary.

from scour.scour import scourString
from scour.scour import sanitizeOptions as sanitizeScourOptions
from scour.scour import parse_args as parseScourArgs

def Optimize(sourcesvg):
    scouroptions = parseScourArgs([
        "--enable-id-stripping",
        "--enable-comment-stripping",
        "--shorten-ids",
        "--indent=none",
        "--no-line-breaks"])
    scouroptions = sanitizeScourOptions(scouroptions)
    optimizedsvg = scourString(sourcesvg, scouroptions)
    return optimizedsvg

(Source)

Of course, as long as this is not an official and documented feature to use Scour functions inside other Python tools, our code can break with any update. smile

This is propably the most resilent solution so far, nice one!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants