src/ztfy/utils/schema.py
branchZTK-1.1
changeset 148 d3668ecd9137
parent 145 1c7e8bef0027
child 165 9615e7d1a4ee
--- /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 <tflorac AT ulthar.net>
+# 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)