Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(471)

Side by Side Diff: reviewbot/third_party/google-api-python-client/apiclient/schema.py

Issue 20515002: Add google-api-python-client in third_party/ (Closed) Base URL: https://src.chromium.org/chrome/trunk/tools/
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 # Copyright (C) 2010 Google Inc.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 """Schema processing for discovery based APIs
16
17 Schemas holds an APIs discovery schemas. It can return those schema as
18 deserialized JSON objects, or pretty print them as prototype objects that
19 conform to the schema.
20
21 For example, given the schema:
22
23 schema = \"\"\"{
24 "Foo": {
25 "type": "object",
26 "properties": {
27 "etag": {
28 "type": "string",
29 "description": "ETag of the collection."
30 },
31 "kind": {
32 "type": "string",
33 "description": "Type of the collection ('calendar#acl').",
34 "default": "calendar#acl"
35 },
36 "nextPageToken": {
37 "type": "string",
38 "description": "Token used to access the next
39 page of this result. Omitted if no further results are available."
40 }
41 }
42 }
43 }\"\"\"
44
45 s = Schemas(schema)
46 print s.prettyPrintByName('Foo')
47
48 Produces the following output:
49
50 {
51 "nextPageToken": "A String", # Token used to access the
52 # next page of this result. Omitted if no further results are available.
53 "kind": "A String", # Type of the collection ('calendar#acl').
54 "etag": "A String", # ETag of the collection.
55 },
56
57 The constructor takes a discovery document in which to look up named schema.
58 """
59
60 # TODO(jcgregorio) support format, enum, minimum, maximum
61
62 __author__ = 'jcgregorio@google.com (Joe Gregorio)'
63
64 import copy
65
66 from oauth2client import util
67 from oauth2client.anyjson import simplejson
68
69
70 class Schemas(object):
71 """Schemas for an API."""
72
73 def __init__(self, discovery):
74 """Constructor.
75
76 Args:
77 discovery: object, Deserialized discovery document from which we pull
78 out the named schema.
79 """
80 self.schemas = discovery.get('schemas', {})
81
82 # Cache of pretty printed schemas.
83 self.pretty = {}
84
85 @util.positional(2)
86 def _prettyPrintByName(self, name, seen=None, dent=0):
87 """Get pretty printed object prototype from the schema name.
88
89 Args:
90 name: string, Name of schema in the discovery document.
91 seen: list of string, Names of schema already seen. Used to handle
92 recursive definitions.
93
94 Returns:
95 string, A string that contains a prototype object with
96 comments that conforms to the given schema.
97 """
98 if seen is None:
99 seen = []
100
101 if name in seen:
102 # Do not fall into an infinite loop over recursive definitions.
103 return '# Object with schema name: %s' % name
104 seen.append(name)
105
106 if name not in self.pretty:
107 self.pretty[name] = _SchemaToStruct(self.schemas[name],
108 seen, dent=dent).to_str(self._prettyPrintByName)
109
110 seen.pop()
111
112 return self.pretty[name]
113
114 def prettyPrintByName(self, name):
115 """Get pretty printed object prototype from the schema name.
116
117 Args:
118 name: string, Name of schema in the discovery document.
119
120 Returns:
121 string, A string that contains a prototype object with
122 comments that conforms to the given schema.
123 """
124 # Return with trailing comma and newline removed.
125 return self._prettyPrintByName(name, seen=[], dent=1)[:-2]
126
127 @util.positional(2)
128 def _prettyPrintSchema(self, schema, seen=None, dent=0):
129 """Get pretty printed object prototype of schema.
130
131 Args:
132 schema: object, Parsed JSON schema.
133 seen: list of string, Names of schema already seen. Used to handle
134 recursive definitions.
135
136 Returns:
137 string, A string that contains a prototype object with
138 comments that conforms to the given schema.
139 """
140 if seen is None:
141 seen = []
142
143 return _SchemaToStruct(schema, seen, dent=dent).to_str(self._prettyPrintByNa me)
144
145 def prettyPrintSchema(self, schema):
146 """Get pretty printed object prototype of schema.
147
148 Args:
149 schema: object, Parsed JSON schema.
150
151 Returns:
152 string, A string that contains a prototype object with
153 comments that conforms to the given schema.
154 """
155 # Return with trailing comma and newline removed.
156 return self._prettyPrintSchema(schema, dent=1)[:-2]
157
158 def get(self, name):
159 """Get deserialized JSON schema from the schema name.
160
161 Args:
162 name: string, Schema name.
163 """
164 return self.schemas[name]
165
166
167 class _SchemaToStruct(object):
168 """Convert schema to a prototype object."""
169
170 @util.positional(3)
171 def __init__(self, schema, seen, dent=0):
172 """Constructor.
173
174 Args:
175 schema: object, Parsed JSON schema.
176 seen: list, List of names of schema already seen while parsing. Used to
177 handle recursive definitions.
178 dent: int, Initial indentation depth.
179 """
180 # The result of this parsing kept as list of strings.
181 self.value = []
182
183 # The final value of the parsing.
184 self.string = None
185
186 # The parsed JSON schema.
187 self.schema = schema
188
189 # Indentation level.
190 self.dent = dent
191
192 # Method that when called returns a prototype object for the schema with
193 # the given name.
194 self.from_cache = None
195
196 # List of names of schema already seen while parsing.
197 self.seen = seen
198
199 def emit(self, text):
200 """Add text as a line to the output.
201
202 Args:
203 text: string, Text to output.
204 """
205 self.value.extend([" " * self.dent, text, '\n'])
206
207 def emitBegin(self, text):
208 """Add text to the output, but with no line terminator.
209
210 Args:
211 text: string, Text to output.
212 """
213 self.value.extend([" " * self.dent, text])
214
215 def emitEnd(self, text, comment):
216 """Add text and comment to the output with line terminator.
217
218 Args:
219 text: string, Text to output.
220 comment: string, Python comment.
221 """
222 if comment:
223 divider = '\n' + ' ' * (self.dent + 2) + '# '
224 lines = comment.splitlines()
225 lines = [x.rstrip() for x in lines]
226 comment = divider.join(lines)
227 self.value.extend([text, ' # ', comment, '\n'])
228 else:
229 self.value.extend([text, '\n'])
230
231 def indent(self):
232 """Increase indentation level."""
233 self.dent += 1
234
235 def undent(self):
236 """Decrease indentation level."""
237 self.dent -= 1
238
239 def _to_str_impl(self, schema):
240 """Prototype object based on the schema, in Python code with comments.
241
242 Args:
243 schema: object, Parsed JSON schema file.
244
245 Returns:
246 Prototype object based on the schema, in Python code with comments.
247 """
248 stype = schema.get('type')
249 if stype == 'object':
250 self.emitEnd('{', schema.get('description', ''))
251 self.indent()
252 if 'properties' in schema:
253 for pname, pschema in schema.get('properties', {}).iteritems():
254 self.emitBegin('"%s": ' % pname)
255 self._to_str_impl(pschema)
256 elif 'additionalProperties' in schema:
257 self.emitBegin('"a_key": ')
258 self._to_str_impl(schema['additionalProperties'])
259 self.undent()
260 self.emit('},')
261 elif '$ref' in schema:
262 schemaName = schema['$ref']
263 description = schema.get('description', '')
264 s = self.from_cache(schemaName, seen=self.seen)
265 parts = s.splitlines()
266 self.emitEnd(parts[0], description)
267 for line in parts[1:]:
268 self.emit(line.rstrip())
269 elif stype == 'boolean':
270 value = schema.get('default', 'True or False')
271 self.emitEnd('%s,' % str(value), schema.get('description', ''))
272 elif stype == 'string':
273 value = schema.get('default', 'A String')
274 self.emitEnd('"%s",' % str(value), schema.get('description', ''))
275 elif stype == 'integer':
276 value = schema.get('default', '42')
277 self.emitEnd('%s,' % str(value), schema.get('description', ''))
278 elif stype == 'number':
279 value = schema.get('default', '3.14')
280 self.emitEnd('%s,' % str(value), schema.get('description', ''))
281 elif stype == 'null':
282 self.emitEnd('None,', schema.get('description', ''))
283 elif stype == 'any':
284 self.emitEnd('"",', schema.get('description', ''))
285 elif stype == 'array':
286 self.emitEnd('[', schema.get('description'))
287 self.indent()
288 self.emitBegin('')
289 self._to_str_impl(schema['items'])
290 self.undent()
291 self.emit('],')
292 else:
293 self.emit('Unknown type! %s' % stype)
294 self.emitEnd('', '')
295
296 self.string = ''.join(self.value)
297 return self.string
298
299 def to_str(self, from_cache):
300 """Prototype object based on the schema, in Python code with comments.
301
302 Args:
303 from_cache: callable(name, seen), Callable that retrieves an object
304 prototype for a schema with the given name. Seen is a list of schema
305 names already seen as we recursively descend the schema definition.
306
307 Returns:
308 Prototype object based on the schema, in Python code with comments.
309 The lines of the code will all be properly indented.
310 """
311 self.from_cache = from_cache
312 return self._to_str_impl(self.schema)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698