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

Side by Side Diff: third_party/google_api_python_client/googleapiclient/schema.py

Issue 963953003: OAuth2 support in depot_tools (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: restore git_cl Created 5 years, 8 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 # Copyright 2014 Google Inc. All Rights Reserved.
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
68
69 class Schemas(object):
70 """Schemas for an API."""
71
72 def __init__(self, discovery):
73 """Constructor.
74
75 Args:
76 discovery: object, Deserialized discovery document from which we pull
77 out the named schema.
78 """
79 self.schemas = discovery.get('schemas', {})
80
81 # Cache of pretty printed schemas.
82 self.pretty = {}
83
84 @util.positional(2)
85 def _prettyPrintByName(self, name, seen=None, dent=0):
86 """Get pretty printed object prototype from the schema name.
87
88 Args:
89 name: string, Name of schema in the discovery document.
90 seen: list of string, Names of schema already seen. Used to handle
91 recursive definitions.
92
93 Returns:
94 string, A string that contains a prototype object with
95 comments that conforms to the given schema.
96 """
97 if seen is None:
98 seen = []
99
100 if name in seen:
101 # Do not fall into an infinite loop over recursive definitions.
102 return '# Object with schema name: %s' % name
103 seen.append(name)
104
105 if name not in self.pretty:
106 self.pretty[name] = _SchemaToStruct(self.schemas[name],
107 seen, dent=dent).to_str(self._prettyPrintByName)
108
109 seen.pop()
110
111 return self.pretty[name]
112
113 def prettyPrintByName(self, name):
114 """Get pretty printed object prototype from the schema name.
115
116 Args:
117 name: string, Name of schema in the discovery document.
118
119 Returns:
120 string, A string that contains a prototype object with
121 comments that conforms to the given schema.
122 """
123 # Return with trailing comma and newline removed.
124 return self._prettyPrintByName(name, seen=[], dent=1)[:-2]
125
126 @util.positional(2)
127 def _prettyPrintSchema(self, schema, seen=None, dent=0):
128 """Get pretty printed object prototype of schema.
129
130 Args:
131 schema: object, Parsed JSON schema.
132 seen: list of string, Names of schema already seen. Used to handle
133 recursive definitions.
134
135 Returns:
136 string, A string that contains a prototype object with
137 comments that conforms to the given schema.
138 """
139 if seen is None:
140 seen = []
141
142 return _SchemaToStruct(schema, seen, dent=dent).to_str(self._prettyPrintByNa me)
143
144 def prettyPrintSchema(self, schema):
145 """Get pretty printed object prototype of schema.
146
147 Args:
148 schema: object, Parsed JSON schema.
149
150 Returns:
151 string, A string that contains a prototype object with
152 comments that conforms to the given schema.
153 """
154 # Return with trailing comma and newline removed.
155 return self._prettyPrintSchema(schema, dent=1)[:-2]
156
157 def get(self, name):
158 """Get deserialized JSON schema from the schema name.
159
160 Args:
161 name: string, Schema name.
162 """
163 return self.schemas[name]
164
165
166 class _SchemaToStruct(object):
167 """Convert schema to a prototype object."""
168
169 @util.positional(3)
170 def __init__(self, schema, seen, dent=0):
171 """Constructor.
172
173 Args:
174 schema: object, Parsed JSON schema.
175 seen: list, List of names of schema already seen while parsing. Used to
176 handle recursive definitions.
177 dent: int, Initial indentation depth.
178 """
179 # The result of this parsing kept as list of strings.
180 self.value = []
181
182 # The final value of the parsing.
183 self.string = None
184
185 # The parsed JSON schema.
186 self.schema = schema
187
188 # Indentation level.
189 self.dent = dent
190
191 # Method that when called returns a prototype object for the schema with
192 # the given name.
193 self.from_cache = None
194
195 # List of names of schema already seen while parsing.
196 self.seen = seen
197
198 def emit(self, text):
199 """Add text as a line to the output.
200
201 Args:
202 text: string, Text to output.
203 """
204 self.value.extend([" " * self.dent, text, '\n'])
205
206 def emitBegin(self, text):
207 """Add text to the output, but with no line terminator.
208
209 Args:
210 text: string, Text to output.
211 """
212 self.value.extend([" " * self.dent, text])
213
214 def emitEnd(self, text, comment):
215 """Add text and comment to the output with line terminator.
216
217 Args:
218 text: string, Text to output.
219 comment: string, Python comment.
220 """
221 if comment:
222 divider = '\n' + ' ' * (self.dent + 2) + '# '
223 lines = comment.splitlines()
224 lines = [x.rstrip() for x in lines]
225 comment = divider.join(lines)
226 self.value.extend([text, ' # ', comment, '\n'])
227 else:
228 self.value.extend([text, '\n'])
229
230 def indent(self):
231 """Increase indentation level."""
232 self.dent += 1
233
234 def undent(self):
235 """Decrease indentation level."""
236 self.dent -= 1
237
238 def _to_str_impl(self, schema):
239 """Prototype object based on the schema, in Python code with comments.
240
241 Args:
242 schema: object, Parsed JSON schema file.
243
244 Returns:
245 Prototype object based on the schema, in Python code with comments.
246 """
247 stype = schema.get('type')
248 if stype == 'object':
249 self.emitEnd('{', schema.get('description', ''))
250 self.indent()
251 if 'properties' in schema:
252 for pname, pschema in schema.get('properties', {}).iteritems():
253 self.emitBegin('"%s": ' % pname)
254 self._to_str_impl(pschema)
255 elif 'additionalProperties' in schema:
256 self.emitBegin('"a_key": ')
257 self._to_str_impl(schema['additionalProperties'])
258 self.undent()
259 self.emit('},')
260 elif '$ref' in schema:
261 schemaName = schema['$ref']
262 description = schema.get('description', '')
263 s = self.from_cache(schemaName, seen=self.seen)
264 parts = s.splitlines()
265 self.emitEnd(parts[0], description)
266 for line in parts[1:]:
267 self.emit(line.rstrip())
268 elif stype == 'boolean':
269 value = schema.get('default', 'True or False')
270 self.emitEnd('%s,' % str(value), schema.get('description', ''))
271 elif stype == 'string':
272 value = schema.get('default', 'A String')
273 self.emitEnd('"%s",' % str(value), schema.get('description', ''))
274 elif stype == 'integer':
275 value = schema.get('default', '42')
276 self.emitEnd('%s,' % str(value), schema.get('description', ''))
277 elif stype == 'number':
278 value = schema.get('default', '3.14')
279 self.emitEnd('%s,' % str(value), schema.get('description', ''))
280 elif stype == 'null':
281 self.emitEnd('None,', schema.get('description', ''))
282 elif stype == 'any':
283 self.emitEnd('"",', schema.get('description', ''))
284 elif stype == 'array':
285 self.emitEnd('[', schema.get('description'))
286 self.indent()
287 self.emitBegin('')
288 self._to_str_impl(schema['items'])
289 self.undent()
290 self.emit('],')
291 else:
292 self.emit('Unknown type! %s' % stype)
293 self.emitEnd('', '')
294
295 self.string = ''.join(self.value)
296 return self.string
297
298 def to_str(self, from_cache):
299 """Prototype object based on the schema, in Python code with comments.
300
301 Args:
302 from_cache: callable(name, seen), Callable that retrieves an object
303 prototype for a schema with the given name. Seen is a list of schema
304 names already seen as we recursively descend the schema definition.
305
306 Returns:
307 Prototype object based on the schema, in Python code with comments.
308 The lines of the code will all be properly indented.
309 """
310 self.from_cache = from_cache
311 return self._to_str_impl(self.schema)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698