171 lines
5.9 KiB
Python
171 lines
5.9 KiB
Python
#!/usr/bin/env python
|
|
#coding:utf-8
|
|
# Author: mozman --<mozman@gmx.at>
|
|
# Purpose: validator2 module - new validator module
|
|
# Created: 01.10.2010
|
|
# Copyright (C) 2010, Manfred Moitzi
|
|
# License: MIT License
|
|
|
|
from svgwrite.data import full11
|
|
from svgwrite.data import tiny12
|
|
from svgwrite.data import pattern
|
|
|
|
validator_cache = {}
|
|
|
|
|
|
def cache_key(profile, debug):
|
|
return str(profile) + str(debug)
|
|
|
|
|
|
def get_validator(profile, debug=True):
|
|
""" Validator factory """
|
|
try:
|
|
return validator_cache[cache_key(profile, debug)]
|
|
except KeyError:
|
|
if profile == 'tiny':
|
|
validator = Tiny12Validator(debug)
|
|
elif profile in ('full', 'basic', 'none'):
|
|
validator = Full11Validator(debug)
|
|
else:
|
|
raise ValueError("Unsupported profile: '%s'" % profile)
|
|
validator_cache[cache_key(profile, debug)] = validator
|
|
return validator
|
|
|
|
|
|
class Tiny12Validator(object):
|
|
profilename = "Tiny 1.2"
|
|
|
|
def __init__(self, debug=True):
|
|
self.debug = debug
|
|
self.attributes = tiny12.attributes
|
|
self.elements = tiny12.elements
|
|
self.typechecker = tiny12.TypeChecker()
|
|
|
|
def check_all_svg_attribute_values(self, elementname, attributes):
|
|
"""
|
|
Check if attributes are valid for object 'elementname' and all svg
|
|
attributes have valid types and values.
|
|
|
|
Raises ValueError.
|
|
"""
|
|
for attributename, value in attributes.items():
|
|
self.check_svg_attribute_value(elementname, attributename, value)
|
|
|
|
def check_svg_attribute_value(self, elementname, attributename, value):
|
|
"""
|
|
Check if 'attributename' is valid for object 'elementname' and 'value'
|
|
is a valid svg type and value.
|
|
|
|
Raises ValueError.
|
|
"""
|
|
self._check_valid_svg_attribute_name(elementname, attributename)
|
|
self._check_svg_value(elementname, attributename, value)
|
|
|
|
def _check_svg_value(self, elementname, attributename, value):
|
|
"""
|
|
Checks if 'value' is a valid svg-type for svg-attribute
|
|
'attributename' at svg-element 'elementname'.
|
|
|
|
Raises TypeError.
|
|
"""
|
|
attribute = self.attributes[attributename]
|
|
# check if 'value' match a valid datatype
|
|
for typename in attribute.get_types(elementname):
|
|
if self.typechecker.check(typename, value):
|
|
return
|
|
# check if 'value' is a valid constant
|
|
valuestr = str(value)
|
|
if not valuestr in attribute.get_const(elementname):
|
|
raise TypeError("'%s' is not a valid value for attribute '%s' at svg-element <%s>." % (value, attributename, elementname))
|
|
|
|
def _check_valid_svg_attribute_name(self, elementname, attributename):
|
|
""" Check if 'attributename' is a valid svg-attribute for svg-element
|
|
'elementname'.
|
|
|
|
Raises ValueError.
|
|
"""
|
|
if not self.is_valid_svg_attribute(elementname, attributename):
|
|
raise ValueError("Invalid attribute '%s' for svg-element <%s>." % (attributename, elementname))
|
|
|
|
def _get_element(self, elementname):
|
|
try:
|
|
return self.elements[elementname]
|
|
except KeyError:
|
|
raise KeyError("<%s> is not valid for selected profile: '%s'." % (elementname, self.profilename))
|
|
|
|
def check_svg_type(self, value, typename='string'):
|
|
"""
|
|
Check if 'value' matches svg type 'typename'.
|
|
|
|
Raises TypeError.
|
|
"""
|
|
if self.typechecker.check(typename, value):
|
|
return value
|
|
else:
|
|
raise TypeError("%s is not of type '%s'." % (value, typename))
|
|
|
|
def is_valid_svg_type(self, value, typename):
|
|
return self.typechecker.check(typename, value)
|
|
|
|
def is_valid_elementname(self, elementname):
|
|
""" True if 'elementname' is a valid svg-element name. """
|
|
return elementname in self.elements
|
|
|
|
def is_valid_svg_attribute(self, elementname, attributename):
|
|
""" True if 'attributename' is a valid svg-attribute for svg-element
|
|
'elementname'.
|
|
"""
|
|
element = self._get_element(elementname)
|
|
return attributename in element.valid_attributes
|
|
|
|
def is_valid_children(self, elementname, childrenname):
|
|
""" True if svg-element 'childrenname' is a valid children of
|
|
svg-element 'elementname'.
|
|
"""
|
|
element = self._get_element(elementname)
|
|
return childrenname in element.valid_children
|
|
|
|
def check_valid_children(self, elementname, childrenname):
|
|
""" Checks if svg-element 'childrenname' is a valid children of
|
|
svg-element 'elementname'.
|
|
|
|
Raises ValueError.
|
|
"""
|
|
if not self.is_valid_children(elementname, childrenname):
|
|
raise ValueError("Invalid children '%s' for svg-element <%s>." % (childrenname, elementname))
|
|
|
|
def get_coordinate(self, value):
|
|
""" Split value in (number, unit) if value has an unit or (number, None).
|
|
|
|
Raises ValueError.
|
|
"""
|
|
|
|
if value is None:
|
|
raise TypeError("Invalid type 'None'.")
|
|
if isinstance(value, (int, float)):
|
|
result = (value, None)
|
|
else:
|
|
result = pattern.coordinate.match(value.strip())
|
|
if result:
|
|
number, tmp, unit = result.groups()
|
|
number = float(number)
|
|
else:
|
|
raise ValueError("'%s' is not a valid svg-coordinate." % value)
|
|
result = (number, unit)
|
|
if self.typechecker.is_number(result[0]):
|
|
return result
|
|
else:
|
|
version = "SVG %s %s" % self.typechecker.get_version()
|
|
raise ValueError("%s is not a valid number for: %s." % (value, version))
|
|
get_length = get_coordinate
|
|
|
|
|
|
class Full11Validator(Tiny12Validator):
|
|
profilename = "Full 1.1"
|
|
|
|
def __init__(self, debug=True):
|
|
self.debug = debug
|
|
self.attributes = full11.attributes
|
|
self.elements = full11.elements
|
|
self.typechecker = full11.TypeChecker()
|