Skip to content

Commit 04c7dfc

Browse files
authored
Add files via upload
1 parent 72238f1 commit 04c7dfc

1 file changed

Lines changed: 102 additions & 29 deletions

File tree

upcean/predraw/predrawsvg.py

Lines changed: 102 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@
2929
except NameError:
3030
basestring = str
3131

32+
try:
33+
unicode # Py2
34+
except NameError:
35+
unicode = str
36+
3237
try:
3338
file
3439
except NameError:
@@ -48,22 +53,27 @@
4853
except Exception:
4954
IOBase = object
5055

56+
try:
57+
import gzip
58+
except ImportError:
59+
gzip = None
60+
5161
# CairoSVG optional conversion
5262
cairosvgsupport = False
53-
svgwrite_valid_extensions = set(["SVG"])
63+
svgwrite_valid_extensions = set(["SVG", "SVGZ"])
5464
if upcean.support.cairosvgsupport:
5565
try:
5666
import cairosvg
5767
cairosvgsupport = True
58-
svgwrite_valid_extensions = set(["SVG", "PDF", "PS", "EPS", "PNG"])
68+
svgwrite_valid_extensions = set(["SVG", "SVGZ", "PDF", "PS", "EPS", "PNG"])
5969
except ImportError:
6070
cairosvgsupport = False
61-
svgwrite_valid_extensions = set(["SVG"])
71+
svgwrite_valid_extensions = set(["SVG", "SVGZ"])
6272

6373
# regex/constants
6474
_RE_URL = re.compile(r"^(ftp|ftps|sftp)://", re.IGNORECASE)
65-
_RE_EXT = re.compile(r"^\.(?P<ext>[A-Za-z]+)$")
66-
_RE_NAME_EXT = re.compile(r"^(?P<name>.+):(?P<ext>[A-Za-z]+)$")
75+
_RE_EXT = re.compile(r"^\.(?P<ext>[A-Za-z0-9]+)$")
76+
_RE_NAME_EXT = re.compile(r"^(?P<name>.+):(?P<ext>[A-Za-z0-9]+)$")
6777

6878

6979
def _is_file_like(x):
@@ -103,6 +113,18 @@ def _svg_bytes_from_dwg(dwg):
103113
return s.encode("utf-8")
104114

105115

116+
def _gzip_bytes(data_bytes, compresslevel=9):
117+
if gzip is None:
118+
raise ImportError("gzip module not available")
119+
out = BytesIO()
120+
gz = gzip.GzipFile(filename="", mode="wb", fileobj=out, compresslevel=compresslevel)
121+
try:
122+
gz.write(data_bytes)
123+
finally:
124+
gz.close()
125+
return out.getvalue()
126+
127+
106128
def _convert_svg_bytes(svg_bytes, fmt, out_fp):
107129
"""
108130
Convert SVG bytes to fmt using CairoSVG, writing into out_fp (file-like or filename).
@@ -130,13 +152,44 @@ def _convert_svg_bytes(svg_bytes, fmt, out_fp):
130152
pass
131153

132154

155+
def _write_bytes_to_target(data, target):
156+
"""
157+
Write bytes to:
158+
- file-like object
159+
- filename path
160+
"""
161+
if _is_file_like(target):
162+
target.write(data)
163+
return True
164+
f = open(target, "wb")
165+
try:
166+
f.write(data)
167+
finally:
168+
f.close()
169+
return True
170+
171+
172+
def _normalize_local_path(path, ext_upper):
173+
"""
174+
For local filesystem paths:
175+
- expand ~ and env vars
176+
- make absolute
177+
- append extension if missing (case-insensitive)
178+
"""
179+
p = os.path.abspath(os.path.expandvars(os.path.expanduser(path)))
180+
ext_l = ext_upper.lower()
181+
if ext_l and not p.lower().endswith("." + ext_l):
182+
p = p + "." + ext_l
183+
return p
184+
185+
133186
def get_save_filename(outfile):
134187
"""
135188
Determine (filename, EXT) where EXT is one of svgwrite_valid_extensions.
136189
Supports:
137190
- None/bool -> passthrough
138191
- file-like or "-" -> (outfile, "SVG")
139-
- "name.ext" or "name:EXT" -> parsed
192+
- "name.ext" or "name:EXT" -> parsed (now includes svgz)
140193
- (name, ext) -> validated
141194
"""
142195
if outfile is None or isinstance(outfile, bool):
@@ -275,10 +328,7 @@ def embed_font(dwg, font_path, font_family):
275328
cache = set()
276329
setattr(dwg, "_embedded_fonts", cache)
277330

278-
try:
279-
fam = unicode(font_family) # Py2
280-
except Exception:
281-
fam = str(font_family)
331+
fam = unicode(font_family)
282332

283333
key = (os.path.abspath(font_path), fam)
284334
if key in cache:
@@ -344,7 +394,8 @@ def embed_font(dwg, font_path, font_family):
344394
def save_to_file(inimage, outfile, outfileext, imgcomment="barcode"):
345395
"""
346396
Save drawsvg.Drawing to:
347-
- SVG directly, or
397+
- SVG directly
398+
- SVGZ (gzip-compressed SVG) <-- added
348399
- PNG/PDF/PS/EPS via CairoSVG (when available)
349400
350401
Behaviors preserved:
@@ -363,56 +414,78 @@ def save_to_file(inimage, outfile, outfileext, imgcomment="barcode"):
363414
# Decide destination
364415
if isinstance(outfile, basestring) and _RE_URL.match(str(outfile)):
365416
upload_target = outfile
366-
# Use BytesIO when converting (CairoSVG) else StringIO is fine
367-
outfp = BytesIO() if (cairosvgsupport and fmt != "SVG") else StringIO()
417+
# SVGZ and conversions are binary; SVG can be text but uploads are bytes anyway.
418+
outfp = BytesIO() if (fmt in ("SVGZ", "PNG", "PDF", "PS", "EPS") or (cairosvgsupport and fmt != "SVG")) else StringIO()
368419
elif outfile == "-":
369420
return_to_var = True
370-
outfp = BytesIO() if (cairosvgsupport and fmt != "SVG") else StringIO()
421+
outfp = BytesIO() if (fmt in ("SVGZ", "PNG", "PDF", "PS", "EPS") or (cairosvgsupport and fmt != "SVG")) else StringIO()
371422
else:
372423
outfp = outfile # filename or file-like
373424

425+
# Normalize local filename strings (append extension if missing)
426+
if isinstance(outfp, basestring) and not _RE_URL.match(str(outfp)) and outfp not in ("", "-"):
427+
outfp = _normalize_local_path(outfp, fmt)
428+
374429
# Write/convert
375-
if cairosvgsupport and fmt in ("PNG", "PDF", "PS", "EPS", "SVG"):
430+
if fmt == "SVGZ":
431+
svg_bytes = _svg_bytes_from_dwg(dwg)
432+
gz_bytes = _gzip_bytes(svg_bytes)
433+
if isinstance(outfp, basestring) and not outfp.lower().endswith(".svgz"):
434+
outfp = outfp + ".svgz"
435+
_write_bytes_to_target(gz_bytes, outfp)
436+
437+
elif cairosvgsupport and fmt in ("PNG", "PDF", "PS", "EPS", "SVG"):
376438
_convert_svg_bytes(_svg_bytes_from_dwg(dwg), fmt, outfp)
439+
377440
else:
378441
# Plain SVG
379442
svg_text = _drawing_to_svg_text(dwg)
380443

381444
if _is_file_like(outfp):
382445
# If it's a binary buffer, write bytes
383446
if isinstance(outfp, BytesIO):
384-
outfp.write(svg_text.encode("utf-8") if not isinstance(svg_text, bytes) else svg_text)
447+
outfp.write(svg_text if isinstance(svg_text, bytes) else svg_text.encode("utf-8"))
385448
else:
386449
try:
387450
outfp.write(svg_text)
388451
except TypeError:
389452
outfp.write(svg_text.encode("utf-8"))
390453
else:
391454
# filename path
392-
if hasattr(dwg, "save_svg") and fmt == "SVG":
393-
dwg.save_svg(outfp)
394-
else:
395-
# Py2: no encoding arg in open()
396-
f = open(outfp, "wb")
397-
try:
398-
b = svg_text if isinstance(svg_text, bytes) else svg_text.encode("utf-8")
399-
f.write(b)
400-
finally:
401-
f.close()
455+
f = open(outfp, "wb")
456+
try:
457+
b = svg_text if isinstance(svg_text, bytes) else svg_text.encode("utf-8")
458+
f.write(b)
459+
finally:
460+
f.close()
402461

403462
# Upload
404463
if upload_target:
464+
# always upload bytes
405465
if isinstance(outfp, BytesIO):
406466
outfp.seek(0)
407467
upload_file_to_internet_file(outfp, upload_target)
408468
outfp.close()
409-
else:
469+
elif _is_file_like(outfp):
410470
outfp.seek(0)
411-
b = BytesIO(outfp.getvalue().encode("utf-8"))
412-
outfp.close()
471+
data = outfp.read()
472+
if not isinstance(data, bytes):
473+
data = data.encode("utf-8")
474+
b = BytesIO()
475+
b.write(data)
413476
b.seek(0)
414477
upload_file_to_internet_file(b, upload_target)
415478
b.close()
479+
try:
480+
outfp.close()
481+
except Exception:
482+
pass
483+
else:
484+
f = open(outfp, "rb")
485+
try:
486+
upload_file_to_internet_file(f, upload_target)
487+
finally:
488+
f.close()
416489
return True
417490

418491
# "-" returns

0 commit comments

Comments
 (0)