1 import os
2
3 import logging
4 logger = logging.getLogger('camelot.types')
5 logger.setLevel(logging.DEBUG)
6
7 from sqlalchemy import types
11 """Sqlalchemy type to store virtual addresses : eg, phone number, e-mail
12 address, ...
13
14 This column type accepts and returns tuples of strings, the first string is
15 the virtual_address_type, and the second the address itself:
16
17 eg: ('mail','project-camelot@conceptive.be') is stored as
18 mail://project-camelot@conceptive.be
19 """
20
21 impl = types.Unicode
22 virtual_address_types = ['phone', 'fax', 'mobile', 'email', 'im', 'pager',]
23
25
26 impl_processor = self.impl.bind_processor(dialect)
27 if not impl_processor:
28 impl_processor = lambda x:x
29
30 def processor(value):
31 if value is not None:
32 value = '://'.join(value)
33 return impl_processor(value)
34
35 return processor
36
38
39 impl_processor = self.impl.result_processor(dialect)
40 if not impl_processor:
41 impl_processor = lambda x:x
42
43 def processor(value):
44
45 if value:
46 return value.split('://')
47 return ('phone','')
48
49 return processor
50
51
52 -class Code(types.TypeDecorator):
53 """Sqlalchemy column type to store codes
54
55 This column type accepts and returns a list of strings and stores them as a
56 string joined with points.
57
58 eg: ['08', 'AB'] is stored as 08.AB
59
60 @param parts: a list of input masks specifying the mask for each part, eg ['99', 'AA'], for
61 valid input masks, see the docs of qlineedit
62 """
63
64 impl = types.Unicode
65
67 import string
68 translator = string.maketrans('', '')
69 self.parts = parts
70 max_length = sum(len(part.translate(translator, '<>!')) for part in parts) + len(parts)
71 types.TypeDecorator.__init__(self, length=max_length, **kwargs)
72
74
75 impl_processor = self.impl.bind_processor(dialect)
76 if not impl_processor:
77 impl_processor = lambda x:x
78
79 def processor(value):
80 if value is not None:
81 value = '.'.join(value)
82 return impl_processor(value)
83
84 return processor
85
87
88 impl_processor = self.impl.result_processor(dialect)
89 if not impl_processor:
90 impl_processor = lambda x:x
91
92 def processor(value):
93
94 if value:
95 return value.split('.')
96 return ['' for p in self.parts]
97
98 return processor
99
104
105 -class RichText(types.TypeDecorator):
106 """Sqlalchemy column type to store rich text
107
108 by default, fields of this type will be displayed within a rich
109 text editor"""
110
111 impl = types.UnicodeText
112
113
114 try:
115 from PIL import Image as PILImage
116 except:
117 import Image as PILImage
121 """Class linking a PIL image and the location and filename where the image is stored"""
122
123 - def __init__(self, image, location=None, filename=None):
124 self.image = image
125 self.location = location
126 self.filename = filename
127
128 @property
130 import os
131 return os.path.join(self.location, self.filename)
132
133
134 -class Image(types.TypeDecorator):
135 """Sqlalchemy column type to store images
136
137 This column type accepts and returns a StoredImage, and stores them in the directory
138 specified by settings.MEDIA_ROOT. The name of the file is stored as a string in
139 the database.
140 """
141
142 impl = types.Unicode
143
144 - def __init__(self, max_length=100, upload_to='', prefix='image-', format='png', **kwargs):
145 import settings
146 self.upload_to = os.path.join(settings.CAMELOT_MEDIA_ROOT, upload_to)
147 self.prefix = prefix
148 self.format = format
149 self.max_length = max_length
150 if not os.path.exists(self.upload_to):
151 os.makedirs(self.upload_to)
152 types.TypeDecorator.__init__(self, length=max_length, **kwargs)
153
155
156 impl_processor = self.impl.bind_processor(dialect)
157 if not impl_processor:
158 impl_processor = lambda x:x
159
160 def processor(value):
161 if value is not None:
162 import tempfile
163 (handle, name) = tempfile.mkstemp(suffix='.%s'%self.format, prefix=self.prefix, dir=os.path.join(self.upload_to))
164 value.image.save(os.fdopen(handle, 'wb'), 'png')
165 value = os.path.basename(name)
166 return impl_processor(value)
167
168 return processor
169
171
172 impl_processor = self.impl.result_processor(dialect)
173 if not impl_processor:
174 impl_processor = lambda x:x
175
176 def processor(value):
177
178 if value:
179 value = os.path.join(self.upload_to, impl_processor(value))
180 if os.path.exists(value):
181 return StoredImage(PILImage.open( value ), self.upload_to, value)
182 else:
183 logger.warn('Image at %s does not exist'%value)
184
185 return processor
186