Skip to content

Commit 154ee24

Browse files
authored
Merge pull request #17 from ReallyNiceGuy/master
Make it work with Python 3
2 parents bc496dc + f3179a8 commit 154ee24

File tree

1 file changed

+56
-46
lines changed

1 file changed

+56
-46
lines changed

svgfig-1.x/svgfig.py

Lines changed: 56 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,15 @@
1919
import re, codecs, os, platform, copy, itertools, math, cmath, random, sys, copy
2020
_epsilon = 1e-5
2121

22+
if sys.version_info >= (3,0):
23+
long = int
24+
basestring = (str,bytes)
25+
26+
# Fix Python 2.x.
27+
try:
28+
UNICODE_EXISTS = bool(type(unicode))
29+
except NameError:
30+
unicode = lambda s: str(s)
2231

2332
if re.search("windows", platform.system(), re.I):
2433
try:
@@ -47,20 +56,21 @@ def rgb(r, g, b, maximum=1.):
4756
max(0, min(b*255./maximum, 255)))
4857

4958
def attr_preprocess(attr):
59+
attrCopy = attr.copy()
5060
for name in attr.keys():
5161
name_colon = re.sub("__", ":", name)
5262
if name_colon != name:
53-
attr[name_colon] = attr[name]
54-
del attr[name]
63+
attrCopy[name_colon] = attrCopy[name]
64+
del attrCopy[name]
5565
name = name_colon
5666

5767
name_dash = re.sub("_", "-", name)
5868
if name_dash != name:
59-
attr[name_dash] = attr[name]
60-
del attr[name]
69+
attrCopy[name_dash] = attrCopy[name]
70+
del attrCopy[name]
6171
name = name_dash
6272

63-
return attr
73+
return attrCopy
6474

6575

6676
class SVG:
@@ -126,7 +136,7 @@ class SVG:
126136
"""
127137
def __init__(self, *t_sub, **attr):
128138
if len(t_sub) == 0:
129-
raise TypeError, "SVG element must have a t (SVG type)"
139+
raise TypeError( "SVG element must have a t (SVG type)")
130140

131141
# first argument is t (SVG type)
132142
self.t = t_sub[0]
@@ -260,7 +270,7 @@ def breadth_first(self, depth_limit=None):
260270
261271
Returns a breadth-first generator over the SVG. If depth_limit
262272
is a number, stop recursion at that depth."""
263-
raise NotImplementedError, "Got an algorithm for breadth-first searching a tree without effectively copying the tree?"
273+
raise NotImplementedError( "Got an algorithm for breadth-first searching a tree without effectively copying the tree?")
264274

265275
def __iter__(self):
266276
return self.depth_first()
@@ -556,7 +566,7 @@ def canvas_outline(*sub, **attr):
556566
svg = canvas(*sub, **attr)
557567
match = re.match(r"[, \t]*([0-9e.+\-]+)[, \t]+([0-9e.+\-]+)[, \t]+([0-9e.+\-]+)[, \t]+([0-9e.+\-]+)[, \t]*", svg["viewBox"])
558568
if match is None:
559-
raise ValueError, "canvas viewBox is incorrectly formatted"
569+
raise ValueError( "canvas viewBox is incorrectly formatted")
560570
x, y, width, height = [float(x) for x in match.groups()]
561571
svg.prepend(SVG("rect", x=x, y=y, width=width, height=height, stroke="none", fill="cornsilk"))
562572
svg.append(SVG("rect", x=x, y=y, width=width, height=height, stroke="black", fill="none"))
@@ -673,7 +683,7 @@ def totrans(expr, vars=("x", "y"), globals=None, locals=None):
673683
return output
674684

675685
else:
676-
raise TypeError, "must be a function of 2 or 1 variables"
686+
raise TypeError( "must be a function of 2 or 1 variables")
677687

678688
if len(vars) == 2:
679689
g = math.__dict__
@@ -694,7 +704,7 @@ def totrans(expr, vars=("x", "y"), globals=None, locals=None):
694704
return output2
695705

696706
else:
697-
raise TypeError, "vars must have 2 or 1 elements"
707+
raise TypeError( "vars must have 2 or 1 elements")
698708

699709

700710
def window(xmin, xmax, ymin, ymax, x=0, y=0, width=100, height=100,
@@ -733,10 +743,10 @@ def window(xmin, xmax, ymin, ymax, x=0, y=0, width=100, height=100,
733743
iy2 = ymax
734744

735745
if xlogbase is not None and (ix1 <= 0. or ix2 <= 0.):
736-
raise ValueError, "x range incompatible with log scaling: (%g, %g)" % (ix1, ix2)
746+
raise ValueError ("x range incompatible with log scaling: (%g, %g)" % (ix1, ix2))
737747

738748
if ylogbase is not None and (iy1 <= 0. or iy2 <= 0.):
739-
raise ValueError, "y range incompatible with log scaling: (%g, %g)" % (iy1, iy2)
749+
raise ValueError ("y range incompatible with log scaling: (%g, %g)" % (iy1, iy2))
740750

741751
def maybelog(t, it1, it2, ot1, ot2, logbase):
742752
if t <= 0.:
@@ -811,7 +821,7 @@ def __init__(self, *d, **kwds):
811821

812822
self.trans = kwds["trans"]; del kwds["trans"]
813823
if len(kwds) != 0:
814-
raise TypeError, "Fig() got unexpected keyword arguments %s" % kwds.keys()
824+
raise TypeError ("Fig() got unexpected keyword arguments %s" % kwds.keys())
815825

816826
def SVG(self, trans=None):
817827
"""Apply the transformation "trans" and return an SVG object.
@@ -929,7 +939,7 @@ def __init__(self, xmin, xmax, ymin, ymax, *d, **kwds):
929939
self.text_attr = kwds["text_attr"]; del kwds["text_attr"]
930940
self.axis_attr = kwds["axis_attr"]; del kwds["axis_attr"]
931941
if len(kwds) != 0:
932-
raise TypeError, "Plot() got unexpected keyword arguments %s" % kwds.keys()
942+
raise TypeError ("Plot() got unexpected keyword arguments %s" % kwds.keys())
933943

934944
def SVG(self, trans=None):
935945
"""Apply the transformation "trans" and return an SVG object."""
@@ -1037,7 +1047,7 @@ def __init__(self, xmin, xmax, ymin, ymax, *d, **kwds):
10371047
self.axis_attr.update(kwds["axis_attr"]); del kwds["axis_attr"]
10381048

10391049
if len(kwds) != 0:
1040-
raise TypeError, "Frame() got unexpected keyword arguments %s" % kwds.keys()
1050+
raise TypeError( "Frame() got unexpected keyword arguments %s" % kwds.keys())
10411051

10421052
def SVG(self):
10431053
"""Apply the window transformation and return an SVG object."""
@@ -1099,7 +1109,7 @@ def SVG(self):
10991109
def pathtoPath(svg):
11001110
"""Converts SVG("path", d="...") into Path(d=[...])."""
11011111
if not isinstance(svg, SVG) or svg.t != "path":
1102-
raise TypeError, "Only SVG <path /> objects can be converted into Paths"
1112+
raise TypeError ("Only SVG <path /> objects can be converted into Paths")
11031113
attr = dict(svg.attr)
11041114
d = attr["d"]
11051115
del attr["d"]
@@ -1233,7 +1243,7 @@ def parse(self, pathdata):
12331243
errstring = "Path command \"%s\" requires a number at index %d" % (command, index)
12341244
num1, index, pathdata = self.parse_number(index, pathdata)
12351245
if num1 is None:
1236-
raise ValueError, errstring
1246+
raise ValueError ( errstring)
12371247

12381248
while num1 is not None:
12391249
output.append((command, num1))
@@ -1246,11 +1256,11 @@ def parse(self, pathdata):
12461256
num2, index, pathdata = self.parse_number(index, pathdata)
12471257

12481258
if num1 is None:
1249-
raise ValueError, errstring
1259+
raise ValueError ( errstring)
12501260

12511261
while num1 is not None:
12521262
if num2 is None:
1253-
raise ValueError, errstring
1263+
raise ValueError ( errstring)
12541264
output.append((command, num1, num2, False))
12551265

12561266
num1, index, pathdata = self.parse_number(index, pathdata)
@@ -1265,11 +1275,11 @@ def parse(self, pathdata):
12651275
num4, index, pathdata = self.parse_number(index, pathdata)
12661276

12671277
if num1 is None:
1268-
raise ValueError, errstring
1278+
raise ValueError ( errstring )
12691279

12701280
while num1 is not None:
12711281
if num2 is None or num3 is None or num4 is None:
1272-
raise ValueError, errstring
1282+
raise ValueError (errstring)
12731283
output.append((command, num1, num2, False, num3, num4, False))
12741284

12751285
num1, index, pathdata = self.parse_number(index, pathdata)
@@ -1288,11 +1298,11 @@ def parse(self, pathdata):
12881298
num6, index, pathdata = self.parse_number(index, pathdata)
12891299

12901300
if num1 is None:
1291-
raise ValueError, errstring
1301+
raise ValueError(errstring)
12921302

12931303
while num1 is not None:
12941304
if num2 is None or num3 is None or num4 is None or num5 is None or num6 is None:
1295-
raise ValueError, errstring
1305+
raise ValueError(errstring)
12961306

12971307
output.append((command, num1, num2, False, num3, num4, False, num5, num6, False))
12981308

@@ -1315,11 +1325,11 @@ def parse(self, pathdata):
13151325
num7, index, pathdata = self.parse_number(index, pathdata)
13161326

13171327
if num1 is None:
1318-
raise ValueError, errstring
1328+
raise ValueError(errstring)
13191329

13201330
while num1 is not None:
13211331
if num2 is None or num3 is None or num4 is None or num5 is None or num6 is None or num7 is None:
1322-
raise ValueError, errstring
1332+
raise ValueError(errstring)
13231333

13241334
output.append((command, num1, num2, False, num3, num4, num5, num6, num7, False))
13251335

@@ -1342,7 +1352,7 @@ def SVG(self, trans=None):
13421352
output = []
13431353
for datum in self.d:
13441354
if not isinstance(datum, (tuple, list)):
1345-
raise TypeError, "pathdata elements must be tuples/lists"
1355+
raise TypeError("pathdata elements must be tuples/lists")
13461356

13471357
command = datum[0]
13481358

@@ -1720,7 +1730,7 @@ def sample(self, trans=None):
17201730
try:
17211731
# the best way to keep all the information while sampling is to make a linked list
17221732
if not (self.low < self.high):
1723-
raise ValueError, "low must be less than high"
1733+
raise ValueError("low must be less than high")
17241734
low, high = self.Sample(float(self.low)), self.Sample(float(self.high))
17251735
low.link(None, high)
17261736
high.link(low, None)
@@ -1911,10 +1921,10 @@ def Path(self, trans=None, local=False):
19111921
vx[i], vy[i] = 0., 0.
19121922

19131923
else:
1914-
raise ValueError, "mode must be \"lines\", \"bezier\", \"velocity\", \"foreback\", \"smooth\", or an abbreviation"
1924+
raise ValueError("mode must be \"lines\", \"bezier\", \"velocity\", \"foreback\", \"smooth\", or an abbreviation")
19151925

19161926
d = []
1917-
indexes = range(len(self.d))
1927+
indexes = list(range(len(self.d)))
19181928
if self.loop and len(self.d) > 0:
19191929
indexes.append(0)
19201930

@@ -2218,7 +2228,7 @@ def SVG(self, trans=None):
22182228
defs.append(make_marker(self.arrow_start, "arrow_start"))
22192229
line.attr["marker-start"] = "url(#%s)" % self.arrow_start
22202230
else:
2221-
raise TypeError, "arrow_start must be False/None or an id string for the new marker"
2231+
raise TypeError("arrow_start must be False/None or an id string for the new marker")
22222232

22232233
if self.arrow_end != False and self.arrow_end is not None:
22242234
if isinstance(self.arrow_end, SVG):
@@ -2228,7 +2238,7 @@ def SVG(self, trans=None):
22282238
defs.append(make_marker(self.arrow_end, "arrow_end"))
22292239
line.attr["marker-end"] = "url(#%s)" % self.arrow_end
22302240
else:
2231-
raise TypeError, "arrow_end must be False/None or an id string for the new marker"
2241+
raise TypeError("arrow_end must be False/None or an id string for the new marker")
22322242

22332243
return SVG("g", defs, line)
22342244

@@ -2314,7 +2324,7 @@ def SVG(self, trans=None):
23142324
defs.append(make_marker(self.arrow_start, "arrow_start"))
23152325
line.attr["marker-start"] = "url(#%s)" % self.arrow_start
23162326
else:
2317-
raise TypeError, "arrow_start must be False/None or an id string for the new marker"
2327+
raise TypeError("arrow_start must be False/None or an id string for the new marker")
23182328

23192329
if self.arrow_end != False and self.arrow_end is not None:
23202330
if isinstance(self.arrow_end, SVG):
@@ -2324,7 +2334,7 @@ def SVG(self, trans=None):
23242334
defs.append(make_marker(self.arrow_end, "arrow_end"))
23252335
line.attr["marker-end"] = "url(#%s)" % self.arrow_end
23262336
else:
2327-
raise TypeError, "arrow_end must be False/None or an id string for the new marker"
2337+
raise TypeError("arrow_end must be False/None or an id string for the new marker")
23282338

23292339
return SVG("g", defs, line)
23302340

@@ -2679,15 +2689,15 @@ def SVG(self, trans=None):
26792689
elif isinstance(self.arrow_start, basestring):
26802690
defs.append(make_marker(self.arrow_start, "arrow_start"))
26812691
else:
2682-
raise TypeError, "arrow_start must be False/None or an id string for the new marker"
2692+
raise TypeError("arrow_start must be False/None or an id string for the new marker")
26832693

26842694
if self.arrow_end != False and self.arrow_end is not None:
26852695
if isinstance(self.arrow_end, SVG):
26862696
defs.append(self.arrow_end)
26872697
elif isinstance(self.arrow_end, basestring):
26882698
defs.append(make_marker(self.arrow_end, "arrow_end"))
26892699
else:
2690-
raise TypeError, "arrow_end must be False/None or an id string for the new marker"
2700+
raise TypeError("arrow_end must be False/None or an id string for the new marker")
26912701

26922702
output.append(defs)
26932703

@@ -2755,7 +2765,7 @@ def interpret(self):
27552765
format = self.labels
27562766

27572767
else:
2758-
raise TypeError, "labels must be None/False, True, a format string, or a number->string function"
2768+
raise TypeError("labels must be None/False, True, a format string, or a number->string function")
27592769

27602770
# Now for the ticks
27612771
ticks = self.ticks
@@ -2791,7 +2801,7 @@ def interpret(self):
27912801
return ticks, []
27922802

27932803
else:
2794-
raise TypeError, "miniticks must be None/False, True, a number of desired miniticks, or a list of numbers"
2804+
raise TypeError("miniticks must be None/False, True, a number of desired miniticks, or a list of numbers")
27952805

27962806
# Cases 3 & 4: ticks is iterable
27972807
elif getattr(ticks, "__iter__", False):
@@ -2828,20 +2838,20 @@ def interpret(self):
28282838
return ticks, []
28292839

28302840
else:
2831-
raise TypeError, "miniticks must be None/False, True, a number of desired miniticks, or a list of numbers"
2841+
raise TypeError("miniticks must be None/False, True, a number of desired miniticks, or a list of numbers")
28322842

28332843
else:
2834-
raise TypeError, "ticks must be None/False, a number of desired ticks, a list of numbers, or a dictionary of explicit markers"
2844+
raise TypeError("ticks must be None/False, a number of desired ticks, a list of numbers, or a dictionary of explicit markers")
28352845

28362846
def compute_ticks(self, N, format):
28372847
"""Return less than -N or exactly N optimal linear ticks.
28382848
28392849
Normally only used internally.
28402850
"""
28412851
if self.low >= self.high:
2842-
raise ValueError, "low must be less than high"
2852+
raise ValueError("low must be less than high")
28432853
if N == 1:
2844-
raise ValueError, "N can be 0 or >1 to specify the exact number of ticks or negative to specify a maximum"
2854+
raise ValueError("N can be 0 or >1 to specify the exact number of ticks or negative to specify a maximum")
28452855

28462856
eps = _epsilon * (self.high - self.low)
28472857

@@ -2946,7 +2956,7 @@ def compute_miniticks(self, original_ticks):
29462956
original_ticks.sort()
29472957

29482958
if self.low > original_ticks[0] + _epsilon or self.high < original_ticks[-1] - _epsilon:
2949-
raise ValueError, "original_ticks {%g...%g} extend beyond [%g, %g]" % (original_ticks[0], original_ticks[-1], self.low, self.high)
2959+
raise ValueError("original_ticks {%g...%g} extend beyond [%g, %g]" % (original_ticks[0], original_ticks[-1], self.low, self.high))
29502960

29512961
granularities = []
29522962
for i in range(len(original_ticks)-1):
@@ -2973,9 +2983,9 @@ def compute_logticks(self, base, N, format):
29732983
Normally only used internally.
29742984
"""
29752985
if self.low >= self.high:
2976-
raise ValueError, "low must be less than high"
2986+
raise ValueError("low must be less than high")
29772987
if N == 1:
2978-
raise ValueError, "N can be 0 or >1 to specify the exact number of ticks or negative to specify a maximum"
2988+
raise ValueError("N can be 0 or >1 to specify the exact number of ticks or negative to specify a maximum")
29792989

29802990
eps = _epsilon * (self.high - self.low)
29812991

@@ -3030,7 +3040,7 @@ def compute_logminiticks(self, base):
30303040
Normally only used internally.
30313041
"""
30323042
if self.low >= self.high:
3033-
raise ValueError, "low must be less than high"
3043+
raise ValueError("low must be less than high")
30343044

30353045
lowN = math.floor(math.log(self.low, base))
30363046
highN = math.ceil(math.log(self.high, base))
@@ -3164,7 +3174,7 @@ def __init__(self, x1, y1, x2, y2, start=0., end=1., ticks=-10, miniticks=True,
31643174
def interpret(self):
31653175
if self.exclude is not None and not (isinstance(self.exclude, (tuple, list)) and len(self.exclude) == 2 and
31663176
isinstance(self.exclude[0], (int, long, float)) and isinstance(self.exclude[1], (int, long, float))):
3167-
raise TypeError, "exclude must either be None or (low, high)"
3177+
raise TypeError("exclude must either be None or (low, high)")
31683178

31693179
ticks, miniticks = Ticks.interpret(self)
31703180
if self.exclude is None:

0 commit comments

Comments
 (0)