1
2
3 """ S3 Encoder/Decoder Base Class
4
5 @copyright: 2011-2019 (c) Sahana Software Foundation
6 @license: MIT
7
8 Permission is hereby granted, free of charge, to any person
9 obtaining a copy of this software and associated documentation
10 files (the "Software"), to deal in the Software without
11 restriction, including without limitation the rights to use,
12 copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the
14 Software is furnished to do so, subject to the following
15 conditions:
16
17 The above copyright notice and this permission notice shall be
18 included in all copies or substantial portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 OTHER DEALINGS IN THE SOFTWARE.
28 """
29
30 __all__ = ("S3Codec",)
31
32 import json
33
34 from xml.sax.saxutils import escape, unescape
35
36 from gluon import current
37
38 from s3utils import s3_str
42 """
43 Base class for converting S3Resources into/from external
44 data formats, for use with S3Importer/S3Exporter
45 """
46
47
48 indices = ["id", "pe_id", "site_id", "sit_id", "item_entity_id"]
49
50 CODECS = {"pdf": "S3RL_PDF",
51 "shp": "S3SHP",
52 "svg": "S3SVG",
53 "xls": "S3XLS",
54 "card": "S3PDFCard",
55 }
56
57
58 @classmethod
60 """
61 Get a codec by representation format
62
63 @param fmt: the representation format (string)
64 """
65
66 codec = cls
67
68 name = cls.CODECS.get(fmt)
69 if name:
70 package = "applications.%s.modules.s3.codecs.%s" % \
71 (current.request.application, fmt)
72 try:
73 codec = getattr(__import__(package, fromlist=[name]), name)
74 except (ImportError, AttributeError):
75 current.log.error("Codec not available: %s" % name)
76 else:
77 current.log.error("No codec found for '%s' format" % fmt)
78
79 return codec()
80
81
82
83
84 - def encode(self, resource, **attr):
85 """
86 API Method to encode a resource in the target format,
87 to be implemented by the subclass (mandatory)
88
89 @param resource: the S3Resource
90
91 @return: a handle to the output
92 """
93 raise NotImplementedError
94
95 - def decode(self, resource, source, **attr):
96 """
97 API Method to decode a source into an S3XML ElementTree,
98 to be implemented by the subclass (if the class does decode)
99
100 @param resource: the S3Resource
101 @param source: the source
102
103 @return: an S3XML ElementTree
104 """
105 return current.xml.tree()
106
107
108
109
110 PY2XML = {"'": "'", '"': """}
111 @classmethod
113 """
114 XML-escape a string
115
116 @param s: the string
117 """
118 if s:
119 s = escape(s, cls.PY2XML)
120 return s
121
122
123 XML2PY = {"'": "'", """: '"'}
124 @classmethod
126 """
127 XML-unescape a string
128
129 @param s: the string
130 """
131 if s:
132 s = unescape(s, cls.XML2PY)
133 return s
134
135
136 @staticmethod
138 """
139 Get a CRUD string
140
141 @param tablename: the table name
142 @param name: the name of the CRUD string
143 """
144
145 crud_strings = current.response.s3.crud_strings
146
147 _crud_strings = crud_strings.get(tablename, crud_strings)
148 return _crud_strings.get(name,
149
150 crud_strings.get(name, None))
151
152
153
154
155 @staticmethod
156 - def json_message(success=True,
157 statuscode=None,
158 message=None,
159 **kwargs):
160 """
161 Provide a nicely-formatted JSON Message
162
163 @param success: action succeeded or failed
164 @param status_code: the HTTP status code
165 @param message: the message text
166 @param kwargs: other elements for the message
167
168 @keyword tree: error tree to include as JSON object (rather
169 than as string) for easy decoding
170 """
171
172 if statuscode is None:
173 statuscode = success and 200 or 404
174
175 status = success and "success" or "failed"
176 code = str(statuscode)
177
178 output = {"status": status, "statuscode": str(code)}
179
180 tree = kwargs.get("tree", None)
181 if message:
182 output["message"] = s3_str(message)
183 for k, v in kwargs.items():
184 if k != "tree":
185 output[k] = v
186 output = json.dumps(output)
187 if message and tree:
188 output = output[:-1] + ', "tree": %s}' % tree
189 return output
190
191
192