source: main/waeup.sirp/branches/ulif-fasttables/src/waeup/sirp/utils/converters.py @ 5235

Last change on this file since 5235 was 4920, checked in by uli, 15 years ago

Make unit tests run again with the new package layout.

File size: 5.4 KB
Line 
1"""Converters for zope.schema-based datatypes.
2"""
3import grok
4from zope.component import getMultiAdapter
5from zope.publisher.browser import TestRequest
6try:
7    from zope.app.form.browser.interfaces import ITerms
8except ImportError:
9    from zope.browser.interfaces import ITerms
10from zope.schema.interfaces import IBool, IText, IInt, IChoice
11from waeup.sirp.interfaces import ISchemaTypeConverter
12
13# If a string has this value, it is considered as 'missing_value' or None.
14NONE_STRING_VALUE = ''
15
16class Converter(grok.Adapter):
17    """Base for string-or-none to zope.schema field converters.
18    """
19    grok.baseclass()
20    grok.provides(ISchemaTypeConverter)
21   
22    def __init__(self, context):
23        """Create a converter with context, a zope.schema.Field, as context.
24        """
25        self.context = context
26
27    def _convertValueFromString(self, string):
28        """You must at least override this method to build a working
29           converter.
30        """
31        raise NotImplementedError('method not implemented')
32   
33    def fromString(self, string=None, strict=True):
34        """Convert ``string`` to value according to assigned field type.
35        """
36        result = None
37        if string is NONE_STRING_VALUE:
38            string = None
39        if string is None:
40            if self.context.required is True:
41                result = self.context.default
42            else:
43                result = self.context.missing_value
44        else:
45            result = self._convertValueFromString(string)
46        if strict:
47            self.context.validate(result)
48        return result
49
50    def _convertValueToString(self, value):
51        return str(value)
52
53    def toString(self, value, strict=True):
54        if strict:
55            self.context.validate(value)
56        if value == self.context.missing_value:
57            return None
58        return self._convertValueToString(value)
59
60class BoolConverter(Converter):
61    """A converter for zope.schema.Bool fields.
62    """
63    grok.context(IBool)
64    grok.provides(ISchemaTypeConverter)
65
66    def _convertValueFromString(self, string):
67        if string is NONE_STRING_VALUE:
68            string = None
69        if string is None:
70            return None
71        if string.lower() in ['1', 'true', 'yes']:
72            return True
73        return False
74
75    def _convertValueToString(self, value):
76        if value is None:
77            return None
78        if value:
79            return '1'
80        return '0'
81   
82class TextConverter(Converter):
83    """A converter for zope.schema.interfaces.IText fields.
84    """
85    grok.context(IText)
86    grok.provides(ISchemaTypeConverter)
87
88    def _convertValueFromString(self, string):
89        return unicode(string)
90
91class IntConverter(Converter):
92    """A converter for zope.schema.Int fields.
93    """
94    grok.context(IInt)
95    grok.provides(ISchemaTypeConverter)
96
97    def _convertValueFromString(self, string):
98        return int(string)
99
100class ChoiceConverter(Converter):
101    """A converter for zope.schema.Choice fields.
102    """
103    grok.context(IChoice)
104    grok.provides(ISchemaTypeConverter)
105
106    tokens = None
107    values = None
108   
109    def __init__(self, context):
110        self.context = context
111        if not hasattr(self.context.source, 'factory'):
112            try:
113                self.terms = getMultiAdapter(
114                    (self.context.source, TestRequest()), ITerms)
115            except:
116                self.terms = None
117
118            return
119        if not hasattr(self.context.source.factory, 'getToken'):
120            return
121        # For expensive token/key lookups we create a 'cache'
122        # here. This speeds up mass operations with many conversions
123        # by factor 10 or more.
124       
125        # Mapping token -> value
126        self.tokens = dict([(self.context.source.factory.getToken(x), x)
127                            for x in self.context.source.factory.getValues()])
128        # Mapping value -> token
129        self.values = dict([(y,x) for x,y in self.tokens.items()])
130
131    def _convertValueFromString(self, string):
132        if self.tokens is not None:
133            return self.tokens[string]
134        if self.terms is not None:
135            return self.terms.getValue(string)
136        return self.context.source.getTermByToken(string).value
137
138    def _convertValueToString(self, value):
139        if self.values is not None:
140            return self.values[value]
141        if self.terms is not None:
142            return self.terms.getTerm(value).token
143        return str(value)
144
145    def fromString(self, string=None, strict=False):
146        """Convert ``string`` to value according to assigned field type.
147
148        We change the default for ``strict``: this disables extra
149        validation checks for Choice fields and saves lots of time. If
150        a string/value is out of allowed range we get a value or key
151        error anyway.
152        """
153        return super(ChoiceConverter, self).fromString(string=string,
154                                                       strict=strict)
155
156    def toString(self, value, strict=False):
157        """Convert ``value`` to string according to assigned field type.
158
159        We change the default for ``strict``: this disables extra
160        validation checks for Choice fields and saves lots of time. If
161        a string/value is out of allowed range we get a value or key
162        error anyway.
163        """
164        return super(ChoiceConverter, self).toString(value=value,
165                                                     strict=strict)
Note: See TracBrowser for help on using the repository browser.