#
# Copyright (c) 2008-2015 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.
#
__docformat__ = 'restructuredtext'
# import standard library
# import interfaces
from pyams_file.interfaces import DELETED_FILE
from pyams_i18n.interfaces.schema import II18nField, II18nTextLineField, II18nTextField, II18nHTMLField, \
II18nFileField, II18nMediaField, II18nThumbnailMediaField, II18nImageField, II18nThumbnailImageField, \
II18nVideoField, II18nThumbnailVideoField, II18nAudioField
from z3c.form.interfaces import NOT_CHANGED, IDataManager
from zope.schema.interfaces import RequiredMissing, WrongType
# import packages
from persistent.mapping import PersistentMapping
from pyams_file.schema import FileField, MediaField, ThumbnailMediaField, ImageField, ThumbnailImageField, \
VideoField, ThumbnailVideoField, AudioField
from pyams_utils.schema import HTMLField
from zope.component import getMultiAdapter
from zope.interface import implementer
from zope.schema import Dict, TextLine, Text
_marker = object()
[docs]class DefaultValueDict(PersistentMapping):
"""Persistent mapping with default value"""
def __init__(self, default=None, *args, **kwargs):
super(DefaultValueDict, self).__init__(*args, **kwargs)
self._default = default
def __missing__(self, key):
return self._default
[docs] def get(self, key, default=None):
result = super(DefaultValueDict, self).get(key, _marker)
if result is _marker:
if default is not None:
return default
else:
return self._default
else:
return result
[docs] def copy(self):
return DefaultValueDict(default=self._default, **self)
[docs]@implementer(II18nField)
class I18nField(Dict):
"""I18n base field class"""
def __init__(self, key_type=None, value_type=None, **kwargs):
# DefaultValueDict.__init__(self, default)
Dict.__init__(self, key_type=TextLine(), value_type=value_type, **kwargs)
def _validate(self, value):
super(I18nField, self)._validate(value)
if self.required:
if self.default:
return
if not value:
raise RequiredMissing
for lang in value.values():
if lang:
return
raise RequiredMissing
[docs]@implementer(II18nTextLineField)
class I18nTextLineField(I18nField):
"""I18n text line field"""
def __init__(self, key_type=None, value_type=None, default=None,
value_constraint=None, value_min_length=0, value_max_length=None, **kwargs):
super(I18nTextLineField, self).__init__(value_type=TextLine(constraint=value_constraint,
min_length=value_min_length,
max_length=value_max_length,
default=default,
required=False),
**kwargs)
[docs]@implementer(II18nTextField)
class I18nTextField(I18nField):
"""I18n text field"""
def __init__(self, key_type=None, value_type=None, default=None,
value_constraint=None, value_min_length=0, value_max_length=None, **kwargs):
super(I18nTextField, self).__init__(value_type=Text(constraint=value_constraint,
min_length=value_min_length,
max_length=value_max_length,
default=default,
required=False),
**kwargs)
[docs]@implementer(II18nHTMLField)
class I18nHTMLField(I18nField):
"""I18n HTML field"""
def __init__(self, key_type=None, value_type=None, default=None,
value_constraint=None, value_min_length=0, value_max_length=None, **kwargs):
super(I18nHTMLField, self).__init__(value_type=HTMLField(constraint=value_constraint,
min_length=value_min_length,
max_length=value_max_length,
default=default,
required=False),
**kwargs)
[docs]@implementer(II18nFileField)
class I18nFileField(I18nField):
"""I18n file field"""
def __init__(self, key_type=None, value_type=None, value_min_length=None, value_max_length=None, **kwargs):
super(I18nFileField, self).__init__(value_type=FileField(min_length=value_min_length,
max_length=value_max_length,
required=False),
**kwargs)
def _validate(self, value):
if self.required:
if self.default:
return
if not value:
raise RequiredMissing
has_value = False
for lang, lang_value in value.items():
# check for NOT_CHANGED value
if lang_value is NOT_CHANGED: # check for empty file value
adapter = getMultiAdapter((self.context, self), IDataManager)
try:
old_value = adapter.query() or {}
except TypeError: # can't adapt field context => new content?
old_value = None
else:
old_value = old_value.get(lang)
has_value = has_value or bool(old_value)
if has_value:
break
elif lang_value is not DELETED_FILE:
has_value = True
break
if not has_value:
raise RequiredMissing
for lang_value in value.values():
if lang_value in (NOT_CHANGED, DELETED_FILE):
return
elif isinstance(lang_value, tuple):
try:
filename, stream = lang_value
if not isinstance(filename, str):
raise WrongType(filename, str, '{0}.filename'.format(self.__name__))
if not hasattr(stream, 'read'):
raise WrongType(stream, '<file-like object>', self.__name__)
except ValueError:
raise WrongType(lang_value, tuple, self.__name__)
elif not self.value_type.schema.providedBy(lang_value):
raise WrongType(lang_value, self.value_type.schema, self.__name__)
[docs]@implementer(II18nImageField)
class I18nImageField(I18nMediaField):
"""I18n image field"""
def __init__(self, key_type=None, value_type=None, value_min_length=None, value_max_length=None, **kwargs):
super(I18nFileField, self).__init__(value_type=ImageField(min_length=value_min_length,
max_length=value_max_length,
required=False),
**kwargs)
[docs]@implementer(II18nThumbnailImageField)
class I18nThumbnailImageField(I18nImageField):
"""I18n thumbnail image field"""
def __init__(self, key_type=None, value_type=None, value_min_length=None, value_max_length=None, **kwargs):
super(I18nFileField, self).__init__(value_type=ThumbnailImageField(min_length=value_min_length,
max_length=value_max_length,
required=False),
**kwargs)
[docs]@implementer(II18nVideoField)
class I18nVideoField(I18nMediaField):
"""I18n video field"""
def __init__(self, key_type=None, value_type=None, value_min_length=None, value_max_length=None, **kwargs):
super(I18nFileField, self).__init__(value_type=VideoField(min_length=value_min_length,
max_length=value_max_length,
required=False),
**kwargs)
[docs]@implementer(II18nThumbnailVideoField)
class I18nThumbnailVideoField(I18nFileField):
"""I18n thumbnail video field"""
def __init__(self, key_type=None, value_type=None, value_min_length=None, value_max_length=None, **kwargs):
super(I18nFileField, self).__init__(value_type=ThumbnailVideoField(min_length=value_min_length,
max_length=value_max_length,
required=False),
**kwargs)
[docs]@implementer(II18nAudioField)
class I18nAudioField(I18nMediaField):
"""I18n audio field"""
def __init__(self, key_type=None, value_type=None, value_min_length=None, value_max_length=None, **kwargs):
super(I18nFileField, self).__init__(value_type=AudioField(min_length=value_min_length,
max_length=value_max_length,
required=False),
**kwargs)