diff -r 044dc196ec8a -r d3668ecd9137 src/ztfy/utils/schema.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ztfy/utils/schema.py Wed Jun 20 16:29:53 2012 +0200 @@ -0,0 +1,110 @@ +### -*- coding: utf-8 -*- #################################################### +############################################################################## +# +# Copyright (c) 2012 Thierry Florac +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# +############################################################################## + + +# import standard packages +import decimal +import string + +# import Zope3 interfaces +from z3c.form.interfaces import IWidget +from zope.schema.interfaces import ITextLine, IDecimal + +# import local interfaces + +# import Zope3 packages +from z3c.form.converter import BaseDataConverter, FormatterValidationError +from zope.component import adapts +from zope.interface import implements +from zope.schema import TextLine, Decimal +from zope.schema._bootstrapfields import InvalidValue + +# import local packages + +from ztfy.utils import _ + + +class StringLine(TextLine): + """String line field""" + + _type = str + + def fromUnicode(self, value): + return str(value) + + +# +# Color field +# + +class IColorField(ITextLine): + """Marker interface for color fields""" + + +class ColorField(TextLine): + """Color field""" + + implements(IColorField) + + def __init__(self, *args, **kw): + super(ColorField, self).__init__(max_length=6, *args, **kw) + + def _validate(self, value): + if len(value) not in (3, 6): + raise InvalidValue, _("Color length must be 3 or 6 characters") + for v in value: + if v not in string.hexdigits: + raise InvalidValue, _("Color value must contain only valid color codes (numbers or letters between 'A' end 'F')") + super(ColorField, self)._validate(value) + + +# +# Pointed decimal field +# + +class IDottedDecimalField(IDecimal): + """Marker interface for dotted decimal fields""" + + +class DottedDecimalField(Decimal): + """Dotted decimal field""" + + implements(IDottedDecimalField) + + +class DottedDecimalDataConverter(BaseDataConverter): + """Dotted decimal field data converter""" + + adapts(IDottedDecimalField, IWidget) + + errorMessage = _('The entered value is not a valid decimal literal.') + + def __init__(self, field, widget): + super(DottedDecimalDataConverter, self).__init__(field, widget) + + def toWidgetValue(self, value): + if not value: + return self.field.missing_value + return str(value) + + def toFieldValue(self, value): + if value is self.field.missing_value: + return u'' + if not value: + return None + try: + return decimal.Decimal(value) + except decimal.InvalidOperation: + raise FormatterValidationError(self.errorMessage, value)