Back to index

plone3  3.1.7
schema.py
Go to the documentation of this file.
00001 ##############################################################################
00002 #
00003 # Copyright (c) 2006 Zope Corporation and Contributors. All Rights Reserved.
00004 #
00005 # This software is subject to the provisions of the Zope Public License,
00006 # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
00007 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
00008 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00009 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
00010 # FOR A PARTICULAR PURPOSE.
00011 #
00012 ##############################################################################
00013 """Formlib schema adapter base classes.
00014 
00015 $Id: schema.py 73035 2007-03-07 16:41:03Z jens $
00016 """
00017 
00018 from datetime import datetime
00019 
00020 from DateTime.DateTime import DateTime
00021 from OFS.Image import Pdata
00022 
00023 from zope.component import getUtility
00024 from zope.datetime import parseDatetimetz
00025 from zope.interface import implements
00026 from zope.schema import BytesLine
00027 from zope.schema.interfaces import IBytesLine
00028 
00029 from Products.CMFCore.interfaces import IPropertiesTool
00030 from Products.CMFDefault.utils import checkEmailAddress
00031 
00032 
00033 class SchemaAdapterBase(object):
00034 
00035     def __init__(self, context):
00036         self.context = context
00037         ptool = getUtility(IPropertiesTool)
00038         self.encoding = ptool.getProperty('default_charset', None)
00039 
00040 
00041 _marker = object()
00042 
00043 class ProxyFieldProperty(object):
00044 
00045     """Computed attributes based on schema fields.
00046 
00047     Based on zope.schema.fieldproperty.FieldProperty.
00048     """
00049 
00050     def __init__(self, field, get_name=None, set_name=None):
00051         if get_name is None:
00052             get_name = field.__name__
00053 
00054         self._field = field
00055         self._get_name = get_name
00056         self._set_name = set_name
00057 
00058     def __get__(self, inst, klass):
00059         if inst is None:
00060             return self
00061 
00062         attribute = getattr(inst.context, self._get_name, _marker)
00063         if attribute is _marker:
00064             field = self._field.bind(inst)
00065             attribute = getattr(field, 'default', _marker)
00066             if attribute is _marker:
00067                 raise AttributeError(self._field.__name__)
00068         elif isinstance(attribute, Pdata):
00069             attribute = str(attribute)
00070         elif callable(attribute):
00071             attribute = attribute()
00072 
00073         if self._field._type == str:
00074             return attribute
00075         if isinstance(attribute, str) and inst.encoding:
00076             return attribute.decode(inst.encoding)
00077         if isinstance(attribute, DateTime):
00078             return parseDatetimetz(attribute.ISO8601())
00079         if isinstance(attribute, (tuple, list)):
00080             if inst.encoding:
00081                 attribute = [ isinstance(v, str)
00082                               and v.decode(inst.encoding) or v
00083                               for v in attribute ]
00084             if self._field._type == list:
00085                 return attribute
00086             if self._field._type == tuple:
00087                 return tuple(attribute)
00088             return set(attribute)
00089         return attribute
00090 
00091     def __set__(self, inst, value):
00092         field = self._field.bind(inst)
00093         field.validate(value)
00094         if field.readonly:
00095             raise ValueError(self._field.__name__, 'field is readonly')
00096         if isinstance(value, unicode) and inst.encoding:
00097             value = value.encode(inst.encoding)
00098         elif isinstance(value, datetime):
00099             value = DateTime(value.isoformat())
00100         elif isinstance(value, (set, tuple, list)):
00101             if inst.encoding:
00102                 value = [ isinstance(v, unicode)
00103                           and v.encode(inst.encoding) or v
00104                           for v in value ]
00105             if not self._field._type == list:
00106                 value = tuple(value)
00107         if self._set_name:
00108             getattr(inst.context, self._set_name)(value)
00109         elif inst.context.hasProperty(self._get_name):
00110             inst.context._updateProperty(self._get_name, value)
00111         else:
00112             setattr(inst.context, self._get_name, value)
00113 
00114     def __getattr__(self, name):
00115         return getattr(self._field, name)
00116 
00117 
00118 class IEmailLine(IBytesLine):
00119 
00120     """A field containing an email address.
00121     """
00122 
00123 
00124 class EmailLine(BytesLine):
00125 
00126     """Email schema field.
00127     """
00128 
00129     implements(IEmailLine)
00130 
00131     default = ''
00132     missing_value = ''
00133 
00134     def _validate(self, value):
00135         super(EmailLine, self)._validate(value)
00136         checkEmailAddress(value)
00137         return True