| Home | Trees | Indices | Help |
|
|---|
|
|
1 """
2 Serialisation of python values to VOTable PARAM values.
3
4 This has two aspects:
5
6 - Guessing proper VOTable type descriptors for python values
7 (use guessParamAttrsForValue)
8 - Serialising the python values to strings suitable for the PARAM.
9 (use serializeToParam)
10 """
11
12 #c Copyright 2008-2019, the GAVO project
13 #c
14 #c This program is free software, covered by the GNU GPL. See the
15 #c COPYING file in the source distribution.
16
17
18 import datetime
19
20 from gavo import utils
21 from gavo.utils import pgsphere
22 from gavo.utils import serializers
23 from gavo.votable import coding
24 from gavo.votable import common
25 from gavo.votable import enc_tabledata
26 from gavo.votable import dec_tabledata
27 from gavo.votable.model import VOTable as V
28
29
30 _SEQUENCE_TYPES = (tuple, list)
31 _ATOMIC_TYPES = [
32 (long, {"datatype": "long"}),
33 (int, {"datatype": "int"}),
34 (str, {"datatype": "char", "arraysize": "*"}),
35 (basestring, {"datatype": "unicodeChar", "arraysize": "*"}),
36 (float, {"datatype": "double"}),
37 (type(None), {"datatype": "double"}),
38 (complex, {"datatype": "doubleComplex"}),
39 (datetime.datetime, {"datatype": "char",
40 "arraysize": "20",
41 "xtype": "timestamp"}),
42 (datetime.date, {"datatype": "char",
43 "arraysize": "20",
44 "xtype": "dachs:DATE"}),
45 (pgsphere.SPoint, {"datatype": "double precision",
46 "arraysize": "2",
47 "xtype": "point"}),
48 (pgsphere.SCircle, {"datatype": "double precision",
49 "arraysize": "3",
50 "xtype": "circle"}),
51 (pgsphere.SPoly, {"datatype": "double precision",
52 "arraysize": "*",
53 "xtype": "polygon"}),]
57 """makes an arraysize attribute for a value with attrs.
58
59 This will in particular check that any existing arraysize in
60 attrs does not end with a star (as variable length is only allowed
61 in the slowest coordinate).
62
63 attrs is changed in place.
64 """
65 if "arraysize" in attrs:
66 if attrs["arraysize"].endswith("*"):
67 raise ValueError("Arrays of variable-length arrays are not allowed.")
68 attrs["arraysize"] = "%sx%s"%(attrs["arraysize"], arraysize)
69 else:
70 attrs["arraysize"] = arraysize
71
74 """helps guessParamAttrsForValue when the value is a sequence.
75 """
76 arraysize = str(len(pythonVal))
77 if len(pythonVal)==0:
78 return {
79 "datatype": "char",
80 "arraysize": "0"}
81
82 elementVal = pythonVal[0]
83
84 if isinstance(elementVal, basestring):
85 # special case as this may become common
86 attrs = {
87 "arraysize": "%sx%s"%(
88 max(len(s) for s in pythonVal), arraysize),
89 "datatype": "char"}
90
91 elif isinstance(elementVal, _SEQUENCE_TYPES):
92 attrs = _guessParamAttrsForSequence(elementVal)
93 _combineArraysize(arraysize, attrs)
94
95 else:
96 attrs = _guessParamAttrsForAtom(elementVal)
97 _combineArraysize(arraysize, attrs)
98
99 return attrs
100
103 """helps guessParamAttrsForValue when the value is atomic.
104
105 (where "atomic" includes string, and other things that actually
106 have non-1 arraysize).
107 """
108 for type, attrs in _ATOMIC_TYPES:
109 if isinstance(pythonVal, type):
110 return attrs.copy()
111
112 raise utils.NotFoundError(repr(pythonVal),
113 "VOTable type code for", "paramval.py predefined types")
114
117 """returns a dict of proposed attributes for a PARAM to keep pythonVal.
118
119 There is, of course, quite a bit of heuristics involved. For instance,
120 we assume sequences are homogeneous.
121 """
122 if isinstance(pythonVal, _SEQUENCE_TYPES):
123 return _guessParamAttrsForSequence(pythonVal)
124
125 else:
126 return _guessParamAttrsForAtom(pythonVal)
127
130 """sets the null literal of param to val.
131 """
132 valEls = list(param.iterChildrenWithName("VALUES"))
133 if valEls:
134 valEls[0](null=val)
135 else:
136 param[V.VALUES(null=val)]
137
140 """changes the VOTable PARAM param so it evaluates to NULL.
141 """
142 if param.datatype in ["float", "double"]:
143 element = "NaN "
144 elif param.datatype in ["unsignedByte", "short", "int", "long"]:
145 element = "99 "
146 _setNULLValue(param, element)
147 elif param.datatype in ["char", "unicodeChar"]:
148 element = "x"
149 _setNULLValue(param, element)
150 else:
151 raise ValueError("No recipe for %s null values"%param.datatype)
152
153 if param.isScalar():
154 param.value = element.strip()
155 elif param.hasVarLength():
156 param.value = ""
157 else:
158 param.value = (element*param.getLength()).strip()
159
162 """A stand-in for serializers.AnnotatedColumn.
163
164 We don't want to use the full thing as it's too fat here, and
165 getVOTSerializer doesn't have the original param anyway (as
166 it shouldn't, as that would break memoization).
167 """
168
172
174 dict.__init__(self, {
175 "nullvalue": "",
176 "name": "anonymous",
177 "dbtype": None,
178 "displayHint": {},
179 "note": None,
180 "ucd": None,
181 "utype": None,
182 "unit": None,
183 "description": None,
184 "id": None,
185 "datatype": datatype,
186 "arraysize": arraysize,
187 "xtype": xtype})
188
192 """returns a function serializing for values of params with the
193 attributes given.
194 """
195 lines = "\n".join([
196 "def codec(val):"]+
197 common.indentList([
198 "val = mapper(val)",
199 "tokens = []"]+
200 enc_tabledata.getLinesFor(V.PARAM(**locals()))+[
201 "return tokens[0]"], " "))
202
203 mapper = serializers.defaultMFRegistry.getMapper(PrimitiveAnnotatedColumn(
204 datatype, arraysize, xtype))
205 env = enc_tabledata.getGlobals(None).copy()
206 env["mapper"] = mapper
207
208 return coding.buildCodec(lines, env)
209
212 """changes the VOTable PARAM param such that val is represented.
213
214 This may involve adding a null value.
215 """
216 if val is None:
217 _serializeNULL(param)
218 else:
219 param.value = getVOTSerializer(
220 param.datatype, param.arraysize, param.xtype)(val)
221
225 """returns a function deserializing values in a param with datatype,
226 arraysize, and xtype.
227 """
228 p = V.PARAM(name="anonymous", datatype=datatype, arraysize=arraysize,
229 xtype=xtype)
230
231 lines = "\n".join([
232 "def codec(val):"]
233 +common.indentList([
234 "row = []"]
235 +dec_tabledata.getLinesFor(p)
236 +[
237 "return row[0]"], " "))
238
239 return coding.buildCodec(lines, dec_tabledata.getGlobals(None))
240
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Thu May 2 07:29:09 2019 | http://epydoc.sourceforge.net |