Consistent whitespace across source files according to PEP 8

(mostly automated by using autopep8, fixes #69)
This commit is contained in:
Eduard Braun 2016-09-15 00:35:13 +02:00
parent 943319b710
commit 0f1974c1e2
8 changed files with 4787 additions and 4276 deletions

View file

@ -1,19 +1,19 @@
###############################################################################
##
## Copyright (C) 2010 Jeff Schiller, 2010 Louis Simard, 2013-2015 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
#
# Copyright (C) 2010 Jeff Schiller, 2010 Louis Simard, 2013-2015 Tavendo GmbH
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
###############################################################################
__version__ = u'0.35'

View file

@ -400,6 +400,7 @@ default_properties = { # excluded all properties with 'auto' as default
'viewport-fill-opacity': '1',
}
def isSameSign(a, b): return (a <= 0 and b <= 0) or (a >= 0 and b >= 0)
scinumber = re.compile(r"[-+]?(\d*\.?)?\d+[eE][-+]?\d+")
@ -407,6 +408,7 @@ number = re.compile(r"[-+]?(\d*\.?)?\d+")
sciExponent = re.compile(r"[eE]([-+]?\d+)")
unit = re.compile("(em|ex|px|pt|pc|cm|mm|in|%){1,1}$")
class Unit(object):
# Integer constants for units.
INVALID = -1
@ -451,7 +453,8 @@ class Unit(object):
# @staticmethod
def get(unitstr):
if unitstr is None: return Unit.NONE
if unitstr is None:
return Unit.NONE
try:
return Unit.s2u[unitstr]
except KeyError:
@ -467,7 +470,9 @@ class Unit(object):
get = staticmethod(get)
str = staticmethod(str)
class SVGLength(object):
def __init__(self, str):
try: # simple unitless and no scientific notation
self.value = float(str)
@ -509,6 +514,7 @@ class SVGLength(object):
self.value = 0
self.units = Unit.INVALID
def findElementsWithId(node, elems=None):
"""
Returns all elements with id attributes
@ -529,6 +535,7 @@ def findElementsWithId(node, elems=None):
referencingProps = ['fill', 'stroke', 'filter', 'clip-path', 'mask', 'marker-start',
'marker-end', 'marker-mid']
def findReferencedElements(node, ids=None):
"""
Returns the number of times an ID is referenced as well as all elements
@ -589,6 +596,7 @@ def findReferencedElements(node, ids=None):
findReferencedElements(child, ids)
return ids
def findReferencingProperty(node, prop, val, ids):
global referencingProps
if prop in referencingProps and val != '':
@ -629,6 +637,7 @@ numBytesSavedInTransforms = 0
numPointsRemovedFromPolygon = 0
numCommentBytes = 0
def removeUnusedDefs(doc, defElem, elemsToRemove=None):
if elemsToRemove is None:
elemsToRemove = []
@ -639,7 +648,7 @@ def removeUnusedDefs(doc, defElem, elemsToRemove=None):
keepTags = ['font', 'style', 'metadata', 'script', 'title', 'desc']
for elem in defElem.childNodes:
# only look at it if an element and not referenced anywhere else
if elem.nodeType == 1 and (elem.getAttribute('id') == '' or \
if elem.nodeType == 1 and (elem.getAttribute('id') == '' or
(not elem.getAttribute('id') in referencedIDs)):
# we only inspect the children of a group in a defs if the group
@ -651,6 +660,7 @@ def removeUnusedDefs(doc, defElem, elemsToRemove=None):
elemsToRemove.append(elem)
return elemsToRemove
def removeUnreferencedElements(doc, keepDefs):
"""
Removes all unreferenced elements except for <svg>, <font>, <metadata>, <title>, and <desc>.
@ -687,6 +697,7 @@ def removeUnreferencedElements(doc, keepDefs):
num += 1
return num
def shortenIDs(doc, prefix, unprotectedElements=None):
"""
Shortens ID names used in the document. ID names referenced the most often are assigned the
@ -731,6 +742,7 @@ def shortenIDs(doc, prefix, unprotectedElements=None):
return num
def intToID(idnum, prefix):
"""
Returns the ID name for the given ID number, spreadsheet-style, i.e. from a to z,
@ -745,6 +757,7 @@ def intToID(idnum, prefix):
return prefix + rid
def renameID(doc, idFrom, idTo, identifiedElements, referencedIDs):
"""
Changes the ID name from idFrom to idTo, on the declaring element
@ -822,6 +835,7 @@ def renameID(doc, idFrom, idTo, identifiedElements, referencedIDs):
return num
def unprotected_ids(doc, options):
u"""Returns a list of unprotected IDs within the document doc."""
identifiedElements = findElementsWithId(doc.documentElement)
@ -847,6 +861,7 @@ def unprotected_ids(doc, options):
del identifiedElements[id]
return identifiedElements
def removeUnreferencedIDs(referencedIDs, identifiedElements):
"""
Removes the unreferenced ID attributes.
@ -855,7 +870,7 @@ def removeUnreferencedIDs(referencedIDs, identifiedElements):
"""
global numIDsRemoved
keepTags = ['font']
num = 0;
num = 0
for id in list(identifiedElements.keys()):
node = identifiedElements[id]
if (id in referencedIDs) == False and not node.nodeName in keepTags:
@ -864,6 +879,7 @@ def removeUnreferencedIDs(referencedIDs, identifiedElements):
num += 1
return num
def removeNamespacedAttributes(node, namespaces):
global numAttrsRemoved
num = 0
@ -885,6 +901,7 @@ def removeNamespacedAttributes(node, namespaces):
num += removeNamespacedAttributes(child, namespaces)
return num
def removeNamespacedElements(node, namespaces):
global numElemsRemoved
num = 0
@ -905,6 +922,7 @@ def removeNamespacedElements(node, namespaces):
num += removeNamespacedElements(child, namespaces)
return num
def removeDescriptiveElements(doc, options):
elementTypes = []
if options.remove_descriptive_elements:
@ -932,6 +950,7 @@ def removeDescriptiveElements(doc, options):
return num
def removeNestedGroups(node):
"""
This walks further and further down the tree, removing groups
@ -968,6 +987,7 @@ def removeNestedGroups(node):
num += removeNestedGroups(child)
return num
def moveCommonAttributesToParentGroup(elem, referencedElements):
"""
This recursively calls this function on all children of the passed in element
@ -992,7 +1012,8 @@ def moveCommonAttributesToParentGroup(elem, referencedElements):
return num
# only process the children if there are more than one element
if len(childElements) <= 1: return num
if len(childElements) <= 1:
return num
commonAttrs = {}
# add all inheritable properties of the first child element
@ -1049,6 +1070,7 @@ def moveCommonAttributesToParentGroup(elem, referencedElements):
num += (len(childElements) - 1) * len(commonAttrs)
return num
def createGroupsForCommonAttributes(elem):
"""
Creates <g> elements to contain runs of 3 or more
@ -1114,17 +1136,21 @@ def createGroupsForCommonAttributes(elem):
while runStart > 0:
nextNode = elem.childNodes.item(runStart - 1)
if nextNode.nodeType == 1:
if nextNode.getAttribute(curAttr) != value: break
if nextNode.getAttribute(curAttr) != value:
break
else:
runElements += 1
runStart -= 1
else: runStart -= 1
else:
runStart -= 1
if runElements >= 3:
# Include whitespace/comment/etc. nodes in the run.
while runEnd < elem.childNodes.length - 1:
if elem.childNodes.item(runEnd + 1).nodeType == 1: break
else: runEnd += 1
if elem.childNodes.item(runEnd + 1).nodeType == 1:
break
else:
runEnd += 1
runLength = runEnd - runStart + 1
if runLength == elem.childNodes.length: # Every child has this
@ -1170,6 +1196,7 @@ def createGroupsForCommonAttributes(elem):
return num
def removeUnusedAttributesOnParent(elem):
"""
This recursively calls this function on all children of the element passed in,
@ -1185,7 +1212,8 @@ def removeUnusedAttributesOnParent(elem):
num += removeUnusedAttributesOnParent(child)
# only process the children if there are more than one element
if len(childElements) <= 1: return num
if len(childElements) <= 1:
return num
# get all attribute values on this parent
attrList = elem.attributes
@ -1223,6 +1251,7 @@ def removeUnusedAttributesOnParent(elem):
return num
def removeDuplicateGradientStops(doc):
global numElemsRemoved
num = 0
@ -1241,8 +1270,10 @@ def removeDuplicateGradientStops(doc):
else:
offset = 0
# set the stop offset value to the integer or floating point equivalent
if int(offset) == offset: stop.setAttribute('offset', str(int(offset)))
else: stop.setAttribute('offset', str(offset))
if int(offset) == offset:
stop.setAttribute('offset', str(int(offset)))
else:
stop.setAttribute('offset', str(offset))
color = stop.getAttribute('stop-color')
opacity = stop.getAttribute('stop-opacity')
@ -1261,6 +1292,7 @@ def removeDuplicateGradientStops(doc):
# linear gradients
return num
def collapseSinglyReferencedGradients(doc):
global numElemsRemoved
num = 0
@ -1318,6 +1350,7 @@ def collapseSinglyReferencedGradients(doc):
num += 1
return num
def removeDuplicateGradients(doc):
global numElemsRemoved
num = 0
@ -1331,7 +1364,8 @@ def removeDuplicateGradients(doc):
# TODO: should slice grads from 'grad' here to optimize
for ograd in grads:
# do not compare gradient to itself
if grad == ograd: continue
if grad == ograd:
continue
# compare grad to ograd (all properties, then all stops)
# if attributes do not match, go to next gradient
@ -1339,9 +1373,10 @@ def removeDuplicateGradients(doc):
for attr in ['gradientUnits', 'spreadMethod', 'gradientTransform', 'x1', 'y1', 'x2', 'y2', 'cx', 'cy', 'fx', 'fy', 'r']:
if grad.getAttribute(attr) != ograd.getAttribute(attr):
someGradAttrsDoNotMatch = True
break;
break
if someGradAttrsDoNotMatch: continue
if someGradAttrsDoNotMatch:
continue
# compare xlink:href values too
if grad.getAttributeNS(NS['XLINK'], 'href') != ograd.getAttributeNS(NS['XLINK'], 'href'):
@ -1351,19 +1386,22 @@ def removeDuplicateGradients(doc):
stops = grad.getElementsByTagName('stop')
ostops = ograd.getElementsByTagName('stop')
if stops.length != ostops.length: continue
if stops.length != ostops.length:
continue
# now compare stops
stopsNotEqual = False
for i in range(stops.length):
if stopsNotEqual: break
if stopsNotEqual:
break
stop = stops.item(i)
ostop = ostops.item(i)
for attr in ['offset', 'stop-color', 'stop-opacity', 'style']:
if stop.getAttribute(attr) != ostop.getAttribute(attr):
stopsNotEqual = True
break
if stopsNotEqual: continue
if stopsNotEqual:
continue
# ograd is a duplicate of grad, we schedule it to be removed UNLESS
# ograd is ALREADY considered a 'master' element
@ -1411,6 +1449,7 @@ def removeDuplicateGradients(doc):
num += 1
return num
def _getStyle(node):
u"""Returns the style attribute of a node as a dictionary."""
if node.nodeType == 1 and len(node.getAttribute('style')) > 0:
@ -1424,6 +1463,7 @@ def _getStyle(node):
else:
return {}
def _setStyle(node, styleMap):
u"""Sets the style attribute of a node to the dictionary ``styleMap``."""
fixedStyle = ';'.join([prop + ':' + styleMap[prop] for prop in list(styleMap.keys())])
@ -1433,6 +1473,7 @@ def _setStyle(node, styleMap):
node.removeAttribute('style')
return node
def repairStyle(node, options):
num = 0
styleMap = _getStyle(node)
@ -1564,6 +1605,7 @@ def repairStyle(node, options):
return num
def styleInheritedFromParent(node, style):
"""
Returns the value of 'style' that is inherited from the parents of the passed-in node
@ -1571,7 +1613,7 @@ def styleInheritedFromParent(node, style):
Warning: This method only considers presentation attributes and inline styles,
any style sheets are ignored!
"""
parentNode = node.parentNode;
parentNode = node.parentNode
# return None if we reached the Document element
if parentNode.nodeType == 9:
@ -1592,6 +1634,7 @@ def styleInheritedFromParent(node, style):
# check the next parent recursively if we did not find a value yet
return styleInheritedFromParent(parentNode, style)
def styleInheritedByChild(node, style, nodeIsChild=False):
"""
Returns whether 'style' is inherited by any children of the passed-in node
@ -1609,7 +1652,6 @@ def styleInheritedByChild(node, style, nodeIsChild=False):
if node.nodeType != 1:
return False
if nodeIsChild:
# if the current child node sets a new value for 'style'
# we can stop the search in the current branch of the DOM tree
@ -1641,6 +1683,7 @@ def styleInheritedByChild(node, style, nodeIsChild=False):
# (e.g nodes without children at the end of the DOM tree, text nodes, ...)
return True
def mayContainTextNodes(node):
"""
Returns True if the passed-in node is probably a text element, or at least
@ -1814,6 +1857,7 @@ default_attributes = [
DefaultAttribute('yChannelSelector', 'A', elements='feDisplacementMap')
]
def taint(taintedSet, taintedAttribute):
u"""Adds an attribute to a set of attributes.
@ -1825,6 +1869,7 @@ def taint(taintedSet, taintedAttribute):
taintedSet.add('marker')
return taintedSet
def removeDefaultAttributeValue(node, attribute):
"""
Removes the DefaultAttribute 'attribute' from 'node' if specified conditions are fulfilled
@ -1851,12 +1896,14 @@ def removeDefaultAttributeValue(node, attribute):
return 0
def removeDefaultAttributeValues(node, options, tainted=set()):
u"""'tainted' keeps a set of attributes defined in parent nodes.
For such attributes, we don't delete attributes with default values."""
num = 0
if node.nodeType != 1: return 0
if node.nodeType != 1:
return 0
# Conditionally remove all default attributes defined in 'default_attributes' (a list of 'DefaultAttribute's)
for attribute in default_attributes:
@ -1892,6 +1939,8 @@ def removeDefaultAttributeValues(node, options, tainted=set()):
rgb = re.compile(r"\s*rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*")
rgbp = re.compile(r"\s*rgb\(\s*(\d*\.?\d+)%\s*,\s*(\d*\.?\d+)%\s*,\s*(\d*\.?\d+)%\s*\)\s*")
def convertColor(value):
"""
Converts the input color string and returns a #RRGGBB (or #RGB if possible) string
@ -1922,17 +1971,19 @@ def convertColor(value):
return s
def convertColors(element):
"""
Recursively converts all color properties into #RRGGBB format if shorter
"""
numBytes = 0
if element.nodeType != 1: return 0
if element.nodeType != 1:
return 0
# set up list of color attributes for each element type
attrsToConvert = []
if element.nodeName in ['rect', 'circle', 'ellipse', 'polygon', \
if element.nodeName in ['rect', 'circle', 'ellipse', 'polygon',
'line', 'polyline', 'path', 'g', 'a']:
attrsToConvert = ['fill', 'stroke']
elif element.nodeName in ['stop']:
@ -1971,6 +2022,8 @@ def convertColors(element):
# TODO: go over what this method does and see if there is a way to optimize it
# TODO: go over the performance of this method and see if I can save memory/speed by
# reusing data structures, etc
def cleanPath(element, options):
"""
Cleans the path string (d attribute) of the element
@ -2318,7 +2371,7 @@ def cleanPath(element, options):
newPath.append(('t', [data[i + 2], data[i + 3]]))
numPathSegmentsReduced += 1
else:
j = 0;
j = 0
while j <= 3:
curveTuples.append(data[i + j])
j += 1
@ -2384,7 +2437,6 @@ def cleanPath(element, options):
element.setAttribute('d', newPathStr)
def parseListOfPoints(s):
"""
Parse string into a list of points.
@ -2419,7 +2471,7 @@ def parseListOfPoints(s):
else:
# unless we accidentally split a number that was in scientific notation
# and had a negative exponent (500.00e-1)
prev = "";
prev = ""
if len(nums):
prev = nums[len(nums) - 1]
if prev and prev[len(prev) - 1] in ['e', 'E']:
@ -2428,7 +2480,8 @@ def parseListOfPoints(s):
nums.append('-' + negcoords[j])
# if we have an odd number of points, return empty
if len(nums) % 2 != 0: return []
if len(nums) % 2 != 0:
return []
# now resolve into Decimal values
i = 0
@ -2444,7 +2497,6 @@ def parseListOfPoints(s):
return nums
def cleanPolygon(elem, options):
"""
Remove unnecessary closing point of polygon points attribute
@ -2462,7 +2514,6 @@ def cleanPolygon(elem, options):
elem.setAttribute('points', scourCoordinates(pts, options, True))
def cleanPolyline(elem, options):
"""
Scour the polyline points attribute
@ -2471,7 +2522,6 @@ def cleanPolyline(elem, options):
elem.setAttribute('points', scourCoordinates(pts, options, True))
def serializePath(pathObj, options):
"""
Reserializes the path data with some cleanups.
@ -2481,7 +2531,6 @@ def serializePath(pathObj, options):
return ''.join([cmd + scourCoordinates(data, options, (cmd == 'a')) for cmd, data in pathObj])
def serializeTransform(transformObj):
"""
Reserializes the transform data with some cleanups.
@ -2494,7 +2543,6 @@ def serializeTransform(transformObj):
)
def scourCoordinates(data, options, forceCommaWsp=False):
"""
Serializes coordinate data with some cleanups:
@ -2545,7 +2593,6 @@ def scourCoordinates(data, options, forceCommaWsp = False):
return ''
def scourLength(length):
"""
Scours a length. Accepts units.
@ -2555,7 +2602,6 @@ def scourLength(length):
return scourUnitlessLength(length.value) + Unit.str(length.units)
def scourUnitlessLength(length, needsRendererWorkaround=False): # length is of a numeric type
"""
Scours the numeric part of a length only. Does not accept units.
@ -2605,7 +2651,6 @@ def scourUnitlessLength(length, needsRendererWorkaround=False): # length is of a
return nonsci
def reducePrecision(element):
"""
Because opacities, letter spacings, stroke widths and all that don't need
@ -2652,7 +2697,6 @@ def reducePrecision(element):
return num
def optimizeAngle(angle):
"""
Because any rotation can be expressed within 360 degrees
@ -2664,18 +2708,21 @@ def optimizeAngle(angle):
# The modulo operator yields results with the sign of the
# divisor, so for negative dividends, we preserve the sign
# of the angle.
if angle < 0: angle %= -360
else: angle %= 360
if angle < 0:
angle %= -360
else:
angle %= 360
# 720 degrees is unneccessary, as 360 covers all angles.
# As "-x" is shorter than "35x" and "-xxx" one character
# longer than positive angles <= 260, we constrain angle
# range to [-90, 270[ (or, equally valid: ]-100, 260]).
if angle >= 270: angle -= 360
elif angle < -90: angle += 360
if angle >= 270:
angle -= 360
elif angle < -90:
angle += 360
return angle
def optimizeTransform(transform):
"""
Optimises a series of transformations parsed from a single
@ -2836,7 +2883,6 @@ def optimizeTransform(transform):
i += 1
def optimizeTransforms(element, options):
"""
Attempts to optimise transform specifications on the given node and its children.
@ -2868,7 +2914,6 @@ def optimizeTransforms(element, options):
return num
def removeComments(element):
"""
Removes comments from the element and its children.
@ -2883,7 +2928,6 @@ def removeComments(element):
removeComments(subelement)
def embedRasters(element, options):
import base64
import urllib
@ -2911,7 +2955,8 @@ def embedRasters(element, options):
# if this is not an absolute path, set path relative
# to script file based on input arg
infilename = '.'
if options.infilename: infilename = options.infilename
if options.infilename:
infilename = options.infilename
href = os.path.join(os.path.dirname(infilename), href)
rasterdata = ''
@ -2942,7 +2987,6 @@ def embedRasters(element, options):
del b64eRaster
def properlySizeDoc(docElement, options):
# get doc width and height
w = SVGLength(docElement.getAttribute('width'))
@ -2984,9 +3028,9 @@ def properlySizeDoc(docElement, options):
docElement.removeAttribute('height')
def remapNamespacePrefix(node, oldprefix, newprefix):
if node == None or node.nodeType != 1: return
if node == None or node.nodeType != 1:
return
if node.prefix == oldprefix:
localName = node.localName
@ -2999,7 +3043,7 @@ def remapNamespacePrefix(node, oldprefix, newprefix):
if newprefix != '':
newNode = doc.createElementNS(namespace, newprefix + ":" + localName)
else:
newNode = doc.createElement(localName);
newNode = doc.createElement(localName)
# add all the attributes
attrList = node.attributes
@ -3021,7 +3065,6 @@ def remapNamespacePrefix(node, oldprefix, newprefix):
remapNamespacePrefix(child, oldprefix, newprefix)
def makeWellFormed(str):
# Don't escape quotation marks for now as they are fine in text nodes
# as well as in attributes if used reciprocally
@ -3039,7 +3082,6 @@ def makeWellFormed(str):
return ''.join([xml_ents[c] if c in xml_ents else c for c in str])
# hand-rolled serialization function that has the following benefits:
# - pretty printing
# - somewhat judicious use of whitespace
@ -3051,8 +3093,10 @@ def serializeXML(element, options, ind = 0, preserveWhitespace = False):
I = ''
newline = ''
if options.newlines:
if options.indent_type == 'tab': I='\t'
elif options.indent_type == 'space': I=' '
if options.indent_type == 'tab':
I = '\t'
elif options.indent_type == 'space':
I = ' '
I *= options.indent_depth
newline = '\n'
@ -3096,7 +3140,8 @@ def serializeXML(element, options, ind = 0, preserveWhitespace = False):
attrIndices += [attrName2Index[name] for name in sorted(attrName2Index.keys())]
for index in attrIndices:
attr = attrList.item(index)
if attr.nodeName == 'id' or attr.nodeName == 'xml:id': continue
if attr.nodeName == 'id' or attr.nodeName == 'xml:id':
continue
# if the attribute value contains a double-quote, use single-quotes
quot = '"'
if attr.nodeValue.find('"') != -1:
@ -3156,17 +3201,19 @@ def serializeXML(element, options, ind = 0, preserveWhitespace = False):
else: # ignore the rest
pass
if onNewLine: outParts.append(I * ind)
if onNewLine:
outParts.append(I * ind)
outParts.extend(['</', element.nodeName, '>'])
if indent > 0: outParts.append(newline)
if indent > 0:
outParts.append(newline)
else:
outParts.append('/>')
if indent > 0: outParts.append(newline)
if indent > 0:
outParts.append(newline)
return "".join(outParts)
# this is the main method
# input is a string representation of the input XML
# returns a string representation of the output XML
@ -3414,7 +3461,6 @@ def scourString(in_string, options=None):
return total_output
# used mostly by unit tests
# input is a filename
# returns the minidom doc representation of the SVG
@ -3438,19 +3484,18 @@ def scourXmlFile(filename, options=None):
return doc
# GZ: Seems most other commandline tools don't do this, is it really wanted?
class HeaderedFormatter(optparse.IndentedHelpFormatter):
"""
Show application name, version number, and copyright statement
above usage information.
"""
def format_usage(self, usage):
return "%s %s\n%s\n%s" % (APP, VER, COPYRIGHT,
optparse.IndentedHelpFormatter.format_usage(self, usage))
# GZ: would prefer this to be in a function or class scope, but tests etc need
# access to the defaults anyway
_options_parser = optparse.OptionParser(
@ -3575,7 +3620,6 @@ _option_group_compatibility.add_option("--error-on-flowtext",
_options_parser.add_option_group(_option_group_compatibility)
def parse_args(args=None, ignore_additional_args=False):
options, rargs = _options_parser.parse_args(args)
@ -3598,10 +3642,10 @@ def parse_args(args=None, ignore_additional_args=False):
return options
def generateDefaultOptions():
## FIXME: clean up this mess/hack and refactor arg parsing to argparse
# FIXME: clean up this mess/hack and refactor arg parsing to argparse
class Struct:
def __init__(self, **entries):
self.__dict__.update(entries)
@ -3610,7 +3654,6 @@ def generateDefaultOptions():
return Struct(**d)
# sanitizes options by updating attributes in a set of defaults options while discarding unknown attributes
def sanitizeOptions(options):
optionsDict = dict((key, getattr(options, key)) for key in dir(options) if not key.startswith('__'))
@ -3621,7 +3664,6 @@ def sanitizeOptions(options):
return sanitizedOptions
def maybe_gziped_file(filename, mode="r"):
if os.path.splitext(filename)[1].lower() in (".svgz", ".gz"):
import gzip
@ -3629,7 +3671,6 @@ def maybe_gziped_file(filename, mode="r"):
return open(filename, mode)
def getInOut(options):
if options.infilename:
infile = maybe_gziped_file(options.infilename, "rb")
@ -3660,7 +3701,6 @@ def getInOut(options):
return [infile, outfile]
def getReport():
return ' Number of elements removed: ' + str(numElemsRemoved) + os.linesep + \
' Number of attributes removed: ' + str(numAttrsRemoved) + os.linesep + \
@ -3677,7 +3717,6 @@ def getReport():
' Number of bytes saved in transformations: ' + str(numBytesSavedInTransforms)
def start(options, input, output):
start = walltime()

View file

@ -48,7 +48,10 @@ from decimal import *
from functools import partial
# Sentinel.
class _EOF(object):
def __repr__(self):
return 'EOF'
EOF = _EOF()
@ -70,6 +73,7 @@ class Lexer(object):
http://www.gooli.org/blog/a-simple-lexer-in-python/
"""
def __init__(self, lexicon):
self.lexicon = lexicon
parts = []
@ -270,7 +274,6 @@ class SVGPathParser(object):
token = next_val_fn()
return x, token
def rule_coordinate_pair(self, next_val_fn, token):
# Inline these since this rule is so common.
if token[0] not in self.number_tokens:

View file

@ -66,6 +66,7 @@ from functools import partial
# Sentinel.
class _EOF(object):
def __repr__(self):
return 'EOF'
EOF = _EOF()
@ -89,6 +90,7 @@ class Lexer(object):
http://www.gooli.org/blog/a-simple-lexer-in-python/
"""
def __init__(self, lexicon):
self.lexicon = lexicon
parts = []

View file

@ -48,6 +48,7 @@
# | DASHMATCH | FUNCTION S* any* ')'
# | '(' S* any* ')' | '[' S* any* ']' ] S*;
def parseCssString(str):
rules = []
# first, split on } to get the rule chunks
@ -55,17 +56,20 @@ def parseCssString(str):
for chunk in chunks:
# second, split on { to get the selector and the list of properties
bits = chunk.split('{')
if len(bits) != 2: continue
if len(bits) != 2:
continue
rule = {}
rule['selector'] = bits[0].strip()
# third, split on ; to get the property declarations
bites = bits[1].strip().split(';')
if len(bites) < 1: continue
if len(bites) < 1:
continue
props = {}
for bite in bites:
# fourth, split on : to get the property name and value
nibbles = bite.strip().split(':')
if len(nibbles) != 2: continue
if len(nibbles) != 2:
continue
props[nibbles[0].strip()] = nibbles[1].strip()
rule['properties'] = props
rules.append(rule)

View file

@ -1,19 +1,19 @@
###############################################################################
##
## Copyright (C) 2013-2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
#
# Copyright (C) 2013-2014 Tavendo GmbH
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
###############################################################################
import os

View file

@ -27,19 +27,24 @@ from scour.yocto_css import parseCssString
class Blank(unittest.TestCase):
def runTest(self):
r = parseCssString('')
self.assertEqual(len(r), 0, 'Blank string returned non-empty list')
self.assertEqual(type(r), type([]), 'Blank string returned non list')
class ElementSelector(unittest.TestCase):
def runTest(self):
r = parseCssString('foo {}')
self.assertEqual(len(r), 1, 'Element selector not returned')
self.assertEqual(r[0]['selector'], 'foo', 'Selector for foo not returned')
self.assertEqual(len(r[0]['properties']), 0, 'Property list for foo not empty')
class ElementSelectorWithProperty(unittest.TestCase):
def runTest(self):
r = parseCssString('foo { bar: baz}')
self.assertEqual(len(r), 1, 'Element selector not returned')

File diff suppressed because it is too large Load diff