Merge pull request #176 from FlyingSamson/read-svg-from-file-like-obj
Support reading of SVGs from strings and file-like objectssupport-stringio-objects
commit
a989c9831d
|
@ -17,6 +17,6 @@ from .document import (Document, CONVERSIONS, CONVERT_ONLY_PATHS,
|
||||||
from .svg_io_sax import SaxDocument
|
from .svg_io_sax import SaxDocument
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from .svg_to_paths import svg2paths, svg2paths2
|
from .svg_to_paths import svg2paths, svg2paths2, svgstr2paths
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -41,6 +41,7 @@ import xml.etree.ElementTree as etree
|
||||||
from xml.etree.ElementTree import Element, SubElement, register_namespace
|
from xml.etree.ElementTree import Element, SubElement, register_namespace
|
||||||
from xml.dom.minidom import parseString
|
from xml.dom.minidom import parseString
|
||||||
import warnings
|
import warnings
|
||||||
|
from io import StringIO
|
||||||
from tempfile import gettempdir
|
from tempfile import gettempdir
|
||||||
from time import time
|
from time import time
|
||||||
|
|
||||||
|
@ -235,13 +236,19 @@ class Document:
|
||||||
The output Path objects will be transformed based on their parent groups.
|
The output Path objects will be transformed based on their parent groups.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
filepath (str): The filepath of the DOM-style object.
|
filepath (str or file-like): The filepath of the
|
||||||
|
DOM-style object or a file-like object containing it.
|
||||||
"""
|
"""
|
||||||
|
self.original_filepath = None
|
||||||
|
|
||||||
# remember location of original svg file
|
# strings are interpreted as file location everything else is treated as
|
||||||
self.original_filepath = filepath
|
# file-like object and passed to the xml parser directly
|
||||||
if filepath is not None and os.path.dirname(filepath) == '':
|
if isinstance(filepath, str):
|
||||||
self.original_filepath = os.path.join(os.getcwd(), filepath)
|
# remember location of original svg file if any
|
||||||
|
self.original_filepath = filepath
|
||||||
|
if os.path.dirname(filepath) == '':
|
||||||
|
self.original_filepath = os.path.join(
|
||||||
|
os.getcwd(), filepath)
|
||||||
|
|
||||||
if filepath is None:
|
if filepath is None:
|
||||||
self.tree = etree.ElementTree(Element('svg'))
|
self.tree = etree.ElementTree(Element('svg'))
|
||||||
|
@ -251,6 +258,16 @@ class Document:
|
||||||
|
|
||||||
self.root = self.tree.getroot()
|
self.root = self.tree.getroot()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_svg_string(cls, svg_string):
|
||||||
|
"""Factory method for creating a document from a string holding a svg
|
||||||
|
object
|
||||||
|
"""
|
||||||
|
# wrap string into StringIO object
|
||||||
|
svg_file_obj = StringIO(svg_string)
|
||||||
|
# create document from file object
|
||||||
|
return Document(svg_file_obj)
|
||||||
|
|
||||||
def paths(self, group_filter=lambda x: True,
|
def paths(self, group_filter=lambda x: True,
|
||||||
path_filter=lambda x: True, path_conversions=CONVERSIONS):
|
path_filter=lambda x: True, path_conversions=CONVERSIONS):
|
||||||
"""Returns a list of all paths in the document.
|
"""Returns a list of all paths in the document.
|
||||||
|
|
|
@ -5,6 +5,7 @@ The main tool being the svg2paths() function."""
|
||||||
from __future__ import division, absolute_import, print_function
|
from __future__ import division, absolute_import, print_function
|
||||||
from xml.dom.minidom import parse
|
from xml.dom.minidom import parse
|
||||||
from os import path as os_path, getcwd
|
from os import path as os_path, getcwd
|
||||||
|
from io import StringIO
|
||||||
import re
|
import re
|
||||||
|
|
||||||
# Internal dependencies
|
# Internal dependencies
|
||||||
|
@ -144,7 +145,9 @@ def svg2paths(svg_file_location,
|
||||||
SVG Path, Line, Polyline, Polygon, Circle, and Ellipse elements.
|
SVG Path, Line, Polyline, Polygon, Circle, and Ellipse elements.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
svg_file_location (string): the location of the svg file
|
svg_file_location (string or file-like object): the location of the
|
||||||
|
svg file on disk or a file-like object containing the content of a
|
||||||
|
svg file
|
||||||
return_svg_attributes (bool): Set to True and a dictionary of
|
return_svg_attributes (bool): Set to True and a dictionary of
|
||||||
svg-attributes will be extracted and returned. See also the
|
svg-attributes will be extracted and returned. See also the
|
||||||
`svg2paths2()` function.
|
`svg2paths2()` function.
|
||||||
|
@ -168,8 +171,12 @@ def svg2paths(svg_file_location,
|
||||||
list: The list of corresponding path attribute dictionaries.
|
list: The list of corresponding path attribute dictionaries.
|
||||||
dict (optional): A dictionary of svg-attributes (see `svg2paths2()`).
|
dict (optional): A dictionary of svg-attributes (see `svg2paths2()`).
|
||||||
"""
|
"""
|
||||||
if os_path.dirname(svg_file_location) == '':
|
# strings are interpreted as file location everything else is treated as
|
||||||
svg_file_location = os_path.join(getcwd(), svg_file_location)
|
# file-like object and passed to the xml parser directly
|
||||||
|
if isinstance(svg_file_location, str):
|
||||||
|
if os_path.dirname(svg_file_location) == '':
|
||||||
|
svg_file_location = os_path.join(
|
||||||
|
getcwd(), svg_file_location)
|
||||||
|
|
||||||
doc = parse(svg_file_location)
|
doc = parse(svg_file_location)
|
||||||
|
|
||||||
|
@ -249,3 +256,26 @@ def svg2paths2(svg_file_location,
|
||||||
convert_polylines_to_paths=convert_polylines_to_paths,
|
convert_polylines_to_paths=convert_polylines_to_paths,
|
||||||
convert_polygons_to_paths=convert_polygons_to_paths,
|
convert_polygons_to_paths=convert_polygons_to_paths,
|
||||||
convert_rectangles_to_paths=convert_rectangles_to_paths)
|
convert_rectangles_to_paths=convert_rectangles_to_paths)
|
||||||
|
|
||||||
|
|
||||||
|
def svgstr2paths(svg_string,
|
||||||
|
return_svg_attributes=False,
|
||||||
|
convert_circles_to_paths=True,
|
||||||
|
convert_ellipses_to_paths=True,
|
||||||
|
convert_lines_to_paths=True,
|
||||||
|
convert_polylines_to_paths=True,
|
||||||
|
convert_polygons_to_paths=True,
|
||||||
|
convert_rectangles_to_paths=True):
|
||||||
|
"""Convenience function; identical to svg2paths() except that it takes the
|
||||||
|
svg object as string. See svg2paths() docstring for more
|
||||||
|
info."""
|
||||||
|
# wrap string into StringIO object
|
||||||
|
svg_file_obj = StringIO(svg_string)
|
||||||
|
return svg2paths(svg_file_location=svg_file_obj,
|
||||||
|
return_svg_attributes=return_svg_attributes,
|
||||||
|
convert_circles_to_paths=convert_circles_to_paths,
|
||||||
|
convert_ellipses_to_paths=convert_ellipses_to_paths,
|
||||||
|
convert_lines_to_paths=convert_lines_to_paths,
|
||||||
|
convert_polylines_to_paths=convert_polylines_to_paths,
|
||||||
|
convert_polygons_to_paths=convert_polygons_to_paths,
|
||||||
|
convert_rectangles_to_paths=convert_rectangles_to_paths)
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
from __future__ import division, absolute_import, print_function
|
||||||
|
import unittest
|
||||||
|
from svgpathtools import *
|
||||||
|
from io import StringIO
|
||||||
|
from io import open # overrides build-in open for compatibility with python2
|
||||||
|
from os.path import join, dirname
|
||||||
|
|
||||||
|
class TestDocument(unittest.TestCase):
|
||||||
|
def test_from_file_path(self):
|
||||||
|
""" Test reading svg from file provided as path """
|
||||||
|
doc = Document(join(dirname(__file__), 'polygons.svg'))
|
||||||
|
|
||||||
|
self.assertEqual(len(doc.paths()), 2)
|
||||||
|
|
||||||
|
def test_from_file_object(self):
|
||||||
|
""" Test reading svg from file object that has already been opened """
|
||||||
|
with open(join(dirname(__file__), 'polygons.svg'), 'r') as file:
|
||||||
|
doc = Document(file)
|
||||||
|
|
||||||
|
self.assertEqual(len(doc.paths()), 2)
|
||||||
|
|
||||||
|
def test_from_stringio(self):
|
||||||
|
""" Test reading svg object contained in a StringIO object """
|
||||||
|
with open(join(dirname(__file__), 'polygons.svg'),
|
||||||
|
'r', encoding='utf-8') as file:
|
||||||
|
# read entire file into string
|
||||||
|
file_content = file.read()
|
||||||
|
# prepare stringio object
|
||||||
|
file_as_stringio = StringIO(file_content)
|
||||||
|
|
||||||
|
doc = Document(file_as_stringio)
|
||||||
|
|
||||||
|
self.assertEqual(len(doc.paths()), 2)
|
||||||
|
|
||||||
|
def test_from_string(self):
|
||||||
|
""" Test reading svg object contained in a string"""
|
||||||
|
with open(join(dirname(__file__), 'polygons.svg'),
|
||||||
|
'r', encoding='utf-8') as file:
|
||||||
|
# read entire file into string
|
||||||
|
file_content = file.read()
|
||||||
|
|
||||||
|
doc = Document.from_svg_string(file_content)
|
||||||
|
|
||||||
|
self.assertEqual(len(doc.paths()), 2)
|
|
@ -1,6 +1,8 @@
|
||||||
from __future__ import division, absolute_import, print_function
|
from __future__ import division, absolute_import, print_function
|
||||||
import unittest
|
import unittest
|
||||||
from svgpathtools import *
|
from svgpathtools import *
|
||||||
|
from io import StringIO
|
||||||
|
from io import open # overrides build-in open for compatibility with python2
|
||||||
from os.path import join, dirname
|
from os.path import join, dirname
|
||||||
|
|
||||||
from svgpathtools.svg_to_paths import rect2pathd
|
from svgpathtools.svg_to_paths import rect2pathd
|
||||||
|
@ -58,3 +60,40 @@ class TestSVG2Paths(unittest.TestCase):
|
||||||
self.assertEqual(rect2pathd(non_rounded), 'M10.0 10.0 L 110.0 10.0 L 110.0 110.0 L 10.0 110.0 z')
|
self.assertEqual(rect2pathd(non_rounded), 'M10.0 10.0 L 110.0 10.0 L 110.0 110.0 L 10.0 110.0 z')
|
||||||
rounded = {"x":"10", "y":"10", "width":"100","height":"100", "rx":"15", "ry": "12"}
|
rounded = {"x":"10", "y":"10", "width":"100","height":"100", "rx":"15", "ry": "12"}
|
||||||
self.assertEqual(rect2pathd(rounded), "M 25.0 10.0 L 95.0 10.0 A 15.0 12.0 0 0 1 110.0 22.0 L 110.0 98.0 A 15.0 12.0 0 0 1 95.0 110.0 L 25.0 110.0 A 15.0 12.0 0 0 1 10.0 98.0 L 10.0 22.0 A 15.0 12.0 0 0 1 25.0 10.0 z")
|
self.assertEqual(rect2pathd(rounded), "M 25.0 10.0 L 95.0 10.0 A 15.0 12.0 0 0 1 110.0 22.0 L 110.0 98.0 A 15.0 12.0 0 0 1 95.0 110.0 L 25.0 110.0 A 15.0 12.0 0 0 1 10.0 98.0 L 10.0 22.0 A 15.0 12.0 0 0 1 25.0 10.0 z")
|
||||||
|
|
||||||
|
def test_from_file_path(self):
|
||||||
|
""" Test reading svg from file provided as path """
|
||||||
|
paths, _ = svg2paths(join(dirname(__file__), 'polygons.svg'))
|
||||||
|
|
||||||
|
self.assertEqual(len(paths), 2)
|
||||||
|
|
||||||
|
def test_from_file_object(self):
|
||||||
|
""" Test reading svg from file object that has already been opened """
|
||||||
|
with open(join(dirname(__file__), 'polygons.svg'), 'r') as file:
|
||||||
|
paths, _ = svg2paths(file)
|
||||||
|
|
||||||
|
self.assertEqual(len(paths), 2)
|
||||||
|
|
||||||
|
def test_from_stringio(self):
|
||||||
|
""" Test reading svg object contained in a StringIO object """
|
||||||
|
with open(join(dirname(__file__), 'polygons.svg'),
|
||||||
|
'r', encoding='utf-8') as file:
|
||||||
|
# read entire file into string
|
||||||
|
file_content = file.read()
|
||||||
|
# prepare stringio object
|
||||||
|
file_as_stringio = StringIO(file_content)
|
||||||
|
|
||||||
|
paths, _ = svg2paths(file_as_stringio)
|
||||||
|
|
||||||
|
self.assertEqual(len(paths), 2)
|
||||||
|
|
||||||
|
def test_from_string(self):
|
||||||
|
""" Test reading svg object contained in a string """
|
||||||
|
with open(join(dirname(__file__), 'polygons.svg'),
|
||||||
|
'r', encoding='utf-8') as file:
|
||||||
|
# read entire file into string
|
||||||
|
file_content = file.read()
|
||||||
|
|
||||||
|
paths, _ = svgstr2paths(file_content)
|
||||||
|
|
||||||
|
self.assertEqual(len(paths), 2)
|
||||||
|
|
Loading…
Reference in New Issue