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

Side by Side Diff: trunk/src/tools/json_schema_compiler/model.py

Issue 25940002: Revert 226826 "This is a preliminary patch to auto-generate the ..." (Closed) Base URL: svn://svn.chromium.org/chrome/
Patch Set: Created 7 years, 2 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
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import os.path 5 import os.path
6 6
7 from json_parse import OrderedDict 7 from json_parse import OrderedDict
8 from memoize import memoize 8 from memoize import memoize
9 9
10
11 class ParseException(Exception): 10 class ParseException(Exception):
12 """Thrown when data in the model is invalid. 11 """Thrown when data in the model is invalid.
13 """ 12 """
14 def __init__(self, parent, message): 13 def __init__(self, parent, message):
15 hierarchy = _GetModelHierarchy(parent) 14 hierarchy = _GetModelHierarchy(parent)
16 hierarchy.append(message) 15 hierarchy.append(message)
17 Exception.__init__( 16 Exception.__init__(
18 self, 'Model parse exception at:\n' + '\n'.join(hierarchy)) 17 self, 'Model parse exception at:\n' + '\n'.join(hierarchy))
19 18
20
21 class Model(object): 19 class Model(object):
22 """Model of all namespaces that comprise an API. 20 """Model of all namespaces that comprise an API.
23 21
24 Properties: 22 Properties:
25 - |namespaces| a map of a namespace name to its model.Namespace 23 - |namespaces| a map of a namespace name to its model.Namespace
26 """ 24 """
27 def __init__(self): 25 def __init__(self):
28 self.namespaces = {} 26 self.namespaces = {}
29 27
30 def AddNamespace(self, json, source_file, include_compiler_options=False): 28 def AddNamespace(self, json, source_file, include_compiler_options=False):
31 """Add a namespace's json to the model and returns the namespace. 29 """Add a namespace's json to the model and returns the namespace.
32 """ 30 """
33 namespace = Namespace(json, 31 namespace = Namespace(json,
34 source_file, 32 source_file,
35 include_compiler_options=include_compiler_options) 33 include_compiler_options=include_compiler_options)
36 self.namespaces[namespace.name] = namespace 34 self.namespaces[namespace.name] = namespace
37 return namespace 35 return namespace
38 36
39
40 def CreateFeature(name, model):
41 if isinstance(model, dict):
42 return SimpleFeature(name, model)
43 return ComplexFeature(name, [SimpleFeature(name, child) for child in model])
44
45
46 class ComplexFeature(object):
47 """A complex feature which may be made of several simple features.
48
49 Properties:
50 - |name| the name of the feature
51 - |unix_name| the unix_name of the feature
52 - |feature_list| a list of simple features which make up the feature
53 """
54 def __init__(self, feature_name, features):
55 self.name = feature_name
56 self.unix_name = UnixName(self.name)
57 self.feature_list = features
58
59 class SimpleFeature(object):
60 """A simple feature, which can make up a complex feature, as specified in
61 files such as chrome/common/extensions/api/_permission_features.json.
62
63 Properties:
64 - |name| the name of the feature
65 - |unix_name| the unix_name of the feature
66 - |channel| the channel where the feature is released
67 - |extension_types| the types which can use the feature
68 - |whitelist| a list of extensions allowed to use the feature
69 """
70 def __init__(self, feature_name, feature_def):
71 self.name = feature_name
72 self.unix_name = UnixName(self.name)
73 self.channel = feature_def['channel']
74 self.extension_types = feature_def['extension_types']
75 self.whitelist = feature_def.get('whitelist')
76
77
78 class Namespace(object): 37 class Namespace(object):
79 """An API namespace. 38 """An API namespace.
80 39
81 Properties: 40 Properties:
82 - |name| the name of the namespace 41 - |name| the name of the namespace
83 - |description| the description of the namespace 42 - |description| the description of the namespace
84 - |unix_name| the unix_name of the namespace 43 - |unix_name| the unix_name of the namespace
85 - |source_file| the file that contained the namespace definition 44 - |source_file| the file that contained the namespace definition
86 - |source_file_dir| the directory component of |source_file| 45 - |source_file_dir| the directory component of |source_file|
87 - |source_file_filename| the filename component of |source_file| 46 - |source_file_filename| the filename component of |source_file|
(...skipping 21 matching lines...) Expand all
109 self.platforms = _GetPlatforms(json) 68 self.platforms = _GetPlatforms(json)
110 toplevel_origin = Origin(from_client=True, from_json=True) 69 toplevel_origin = Origin(from_client=True, from_json=True)
111 self.types = _GetTypes(self, json, self, toplevel_origin) 70 self.types = _GetTypes(self, json, self, toplevel_origin)
112 self.functions = _GetFunctions(self, json, self) 71 self.functions = _GetFunctions(self, json, self)
113 self.events = _GetEvents(self, json, self) 72 self.events = _GetEvents(self, json, self)
114 self.properties = _GetProperties(self, json, self, toplevel_origin) 73 self.properties = _GetProperties(self, json, self, toplevel_origin)
115 self.compiler_options = (json.get('compiler_options', {}) 74 self.compiler_options = (json.get('compiler_options', {})
116 if include_compiler_options else {}) 75 if include_compiler_options else {})
117 self.documentation_options = json.get('documentation_options', {}) 76 self.documentation_options = json.get('documentation_options', {})
118 77
119
120 class Origin(object): 78 class Origin(object):
121 """Stores the possible origin of model object as a pair of bools. These are: 79 """Stores the possible origin of model object as a pair of bools. These are:
122 80
123 |from_client| indicating that instances can originate from users of 81 |from_client| indicating that instances can originate from users of
124 generated code (for example, function results), or 82 generated code (for example, function results), or
125 |from_json| indicating that instances can originate from the JSON (for 83 |from_json| indicating that instances can originate from the JSON (for
126 example, function parameters) 84 example, function parameters)
127 85
128 It is possible for model objects to originate from both the client and json, 86 It is possible for model objects to originate from both the client and json,
129 for example Types defined in the top-level schema, in which case both 87 for example Types defined in the top-level schema, in which case both
130 |from_client| and |from_json| would be True. 88 |from_client| and |from_json| would be True.
131 """ 89 """
132 def __init__(self, from_client=False, from_json=False): 90 def __init__(self, from_client=False, from_json=False):
133 if not from_client and not from_json: 91 if not from_client and not from_json:
134 raise ValueError('One of from_client or from_json must be true') 92 raise ValueError('One of from_client or from_json must be true')
135 self.from_client = from_client 93 self.from_client = from_client
136 self.from_json = from_json 94 self.from_json = from_json
137 95
138
139 class Type(object): 96 class Type(object):
140 """A Type defined in the json. 97 """A Type defined in the json.
141 98
142 Properties: 99 Properties:
143 - |name| the type name 100 - |name| the type name
144 - |namespace| the Type's namespace 101 - |namespace| the Type's namespace
145 - |description| the description of the type (if provided) 102 - |description| the description of the type (if provided)
146 - |properties| a map of property unix_names to their model.Property 103 - |properties| a map of property unix_names to their model.Property
147 - |functions| a map of function names to their model.Function 104 - |functions| a map of function names to their model.Function
148 - |events| a map of event names to their model.Event 105 - |events| a map of event names to their model.Event
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
235 self.additional_properties = None 192 self.additional_properties = None
236 elif json_type == 'function': 193 elif json_type == 'function':
237 self.property_type = PropertyType.FUNCTION 194 self.property_type = PropertyType.FUNCTION
238 # Sometimes we might have an unnamed function, e.g. if it's a property 195 # Sometimes we might have an unnamed function, e.g. if it's a property
239 # of an object. Use the name of the property in that case. 196 # of an object. Use the name of the property in that case.
240 function_name = json.get('name', name) 197 function_name = json.get('name', name)
241 self.function = Function(self, function_name, json, namespace, origin) 198 self.function = Function(self, function_name, json, namespace, origin)
242 else: 199 else:
243 raise ParseException(self, 'Unsupported JSON type %s' % json_type) 200 raise ParseException(self, 'Unsupported JSON type %s' % json_type)
244 201
245
246 class Function(object): 202 class Function(object):
247 """A Function defined in the API. 203 """A Function defined in the API.
248 204
249 Properties: 205 Properties:
250 - |name| the function name 206 - |name| the function name
251 - |platforms| if not None, the list of platforms that the function is 207 - |platforms| if not None, the list of platforms that the function is
252 available to 208 available to
253 - |params| a list of parameters to the function (order matters). A separate 209 - |params| a list of parameters to the function (order matters). A separate
254 parameter is used for each choice of a 'choices' parameter 210 parameter is used for each choice of a 'choices' parameter
255 - |description| a description of the function (if provided) 211 - |description| a description of the function (if provided)
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
307 Origin(from_client=True)) 263 Origin(from_client=True))
308 264
309 self.returns = None 265 self.returns = None
310 if 'returns' in json: 266 if 'returns' in json:
311 self.returns = Type(self, 267 self.returns = Type(self,
312 '%sReturnType' % name, 268 '%sReturnType' % name,
313 json['returns'], 269 json['returns'],
314 namespace, 270 namespace,
315 origin) 271 origin)
316 272
317
318 class Property(object): 273 class Property(object):
319 """A property of a type OR a parameter to a function. 274 """A property of a type OR a parameter to a function.
320 Properties: 275 Properties:
321 - |name| name of the property as in the json. This shouldn't change since 276 - |name| name of the property as in the json. This shouldn't change since
322 it is the key used to access DictionaryValues 277 it is the key used to access DictionaryValues
323 - |unix_name| the unix_style_name of the property. Used as variable name 278 - |unix_name| the unix_style_name of the property. Used as variable name
324 - |optional| a boolean representing whether the property is optional 279 - |optional| a boolean representing whether the property is optional
325 - |description| a description of the property (if provided) 280 - |description| a description of the property (if provided)
326 - |type_| the model.Type of this property 281 - |type_| the model.Type of this property
327 - |simple_name| the name of this Property without a namespace 282 - |simple_name| the name of this Property without a namespace
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 return 334 return
380 if self._unix_name_used: 335 if self._unix_name_used:
381 raise AttributeError( 336 raise AttributeError(
382 'Cannot set the unix_name on %s; ' 337 'Cannot set the unix_name on %s; '
383 'it is already used elsewhere as %s' % 338 'it is already used elsewhere as %s' %
384 (self.name, self._unix_name)) 339 (self.name, self._unix_name))
385 self._unix_name = unix_name 340 self._unix_name = unix_name
386 341
387 unix_name = property(GetUnixName, SetUnixName) 342 unix_name = property(GetUnixName, SetUnixName)
388 343
389
390 class _Enum(object): 344 class _Enum(object):
391 """Superclass for enum types with a "name" field, setting up repr/eq/ne. 345 """Superclass for enum types with a "name" field, setting up repr/eq/ne.
392 Enums need to do this so that equality/non-equality work over pickling. 346 Enums need to do this so that equality/non-equality work over pickling.
393 """ 347 """
394 @staticmethod 348 @staticmethod
395 def GetAll(cls): 349 def GetAll(cls):
396 """Yields all _Enum objects declared in |cls|. 350 """Yields all _Enum objects declared in |cls|.
397 """ 351 """
398 for prop_key in dir(cls): 352 for prop_key in dir(cls):
399 prop_value = getattr(cls, prop_key) 353 prop_value = getattr(cls, prop_key)
400 if isinstance(prop_value, _Enum): 354 if isinstance(prop_value, _Enum):
401 yield prop_value 355 yield prop_value
402 356
403 def __init__(self, name): 357 def __init__(self, name):
404 self.name = name 358 self.name = name
405 359
406 def __eq__(self, other): 360 def __eq__(self, other):
407 return type(other) == type(self) and other.name == self.name 361 return type(other) == type(self) and other.name == self.name
408 def __ne__(self, other): 362 def __ne__(self, other):
409 return not (self == other) 363 return not (self == other)
410 364
411 def __repr__(self): 365 def __repr__(self):
412 return self.name 366 return self.name
413 367
414 def __str__(self): 368 def __str__(self):
415 return repr(self) 369 return repr(self)
416 370
417
418 class _PropertyTypeInfo(_Enum): 371 class _PropertyTypeInfo(_Enum):
419 def __init__(self, is_fundamental, name): 372 def __init__(self, is_fundamental, name):
420 _Enum.__init__(self, name) 373 _Enum.__init__(self, name)
421 self.is_fundamental = is_fundamental 374 self.is_fundamental = is_fundamental
422 375
423
424 class PropertyType(object): 376 class PropertyType(object):
425 """Enum of different types of properties/parameters. 377 """Enum of different types of properties/parameters.
426 """ 378 """
427 ANY = _PropertyTypeInfo(False, "any") 379 ANY = _PropertyTypeInfo(False, "any")
428 ARRAY = _PropertyTypeInfo(False, "array") 380 ARRAY = _PropertyTypeInfo(False, "array")
429 BINARY = _PropertyTypeInfo(False, "binary") 381 BINARY = _PropertyTypeInfo(False, "binary")
430 BOOLEAN = _PropertyTypeInfo(True, "boolean") 382 BOOLEAN = _PropertyTypeInfo(True, "boolean")
431 CHOICES = _PropertyTypeInfo(False, "choices") 383 CHOICES = _PropertyTypeInfo(False, "choices")
432 DOUBLE = _PropertyTypeInfo(True, "double") 384 DOUBLE = _PropertyTypeInfo(True, "double")
433 ENUM = _PropertyTypeInfo(False, "enum") 385 ENUM = _PropertyTypeInfo(False, "enum")
434 FUNCTION = _PropertyTypeInfo(False, "function") 386 FUNCTION = _PropertyTypeInfo(False, "function")
435 INT64 = _PropertyTypeInfo(True, "int64") 387 INT64 = _PropertyTypeInfo(True, "int64")
436 INTEGER = _PropertyTypeInfo(True, "integer") 388 INTEGER = _PropertyTypeInfo(True, "integer")
437 OBJECT = _PropertyTypeInfo(False, "object") 389 OBJECT = _PropertyTypeInfo(False, "object")
438 REF = _PropertyTypeInfo(False, "ref") 390 REF = _PropertyTypeInfo(False, "ref")
439 STRING = _PropertyTypeInfo(True, "string") 391 STRING = _PropertyTypeInfo(True, "string")
440 392
441
442 @memoize 393 @memoize
443 def UnixName(name): 394 def UnixName(name):
444 '''Returns the unix_style name for a given lowerCamelCase string. 395 '''Returns the unix_style name for a given lowerCamelCase string.
445 ''' 396 '''
446 unix_name = [] 397 unix_name = []
447 for i, c in enumerate(name): 398 for i, c in enumerate(name):
448 if c.isupper() and i > 0 and name[i - 1] != '_': 399 if c.isupper() and i > 0 and name[i - 1] != '_':
449 # Replace lowerUpper with lower_Upper. 400 # Replace lowerUpper with lower_Upper.
450 if name[i - 1].islower(): 401 if name[i - 1].islower():
451 unix_name.append('_') 402 unix_name.append('_')
452 # Replace ACMEWidgets with ACME_Widgets 403 # Replace ACMEWidgets with ACME_Widgets
453 elif i + 1 < len(name) and name[i + 1].islower(): 404 elif i + 1 < len(name) and name[i + 1].islower():
454 unix_name.append('_') 405 unix_name.append('_')
455 if c == '.': 406 if c == '.':
456 # Replace hello.world with hello_world. 407 # Replace hello.world with hello_world.
457 unix_name.append('_') 408 unix_name.append('_')
458 else: 409 else:
459 # Everything is lowercase. 410 # Everything is lowercase.
460 unix_name.append(c.lower()) 411 unix_name.append(c.lower())
461 return ''.join(unix_name) 412 return ''.join(unix_name)
462 413
463
464 def _StripNamespace(name, namespace): 414 def _StripNamespace(name, namespace):
465 if name.startswith(namespace.name + '.'): 415 if name.startswith(namespace.name + '.'):
466 return name[len(namespace.name + '.'):] 416 return name[len(namespace.name + '.'):]
467 return name 417 return name
468 418
469
470 def _GetModelHierarchy(entity): 419 def _GetModelHierarchy(entity):
471 """Returns the hierarchy of the given model entity.""" 420 """Returns the hierarchy of the given model entity."""
472 hierarchy = [] 421 hierarchy = []
473 while entity is not None: 422 while entity is not None:
474 hierarchy.append(getattr(entity, 'name', repr(entity))) 423 hierarchy.append(getattr(entity, 'name', repr(entity)))
475 if isinstance(entity, Namespace): 424 if isinstance(entity, Namespace):
476 hierarchy.insert(0, ' in %s' % entity.source_file) 425 hierarchy.insert(0, ' in %s' % entity.source_file)
477 entity = getattr(entity, 'parent', None) 426 entity = getattr(entity, 'parent', None)
478 hierarchy.reverse() 427 hierarchy.reverse()
479 return hierarchy 428 return hierarchy
480 429
481
482 def _GetTypes(parent, json, namespace, origin): 430 def _GetTypes(parent, json, namespace, origin):
483 """Creates Type objects extracted from |json|. 431 """Creates Type objects extracted from |json|.
484 """ 432 """
485 types = OrderedDict() 433 types = OrderedDict()
486 for type_json in json.get('types', []): 434 for type_json in json.get('types', []):
487 type_ = Type(parent, type_json['id'], type_json, namespace, origin) 435 type_ = Type(parent, type_json['id'], type_json, namespace, origin)
488 types[type_.name] = type_ 436 types[type_.name] = type_
489 return types 437 return types
490 438
491
492 def _GetFunctions(parent, json, namespace): 439 def _GetFunctions(parent, json, namespace):
493 """Creates Function objects extracted from |json|. 440 """Creates Function objects extracted from |json|.
494 """ 441 """
495 functions = OrderedDict() 442 functions = OrderedDict()
496 for function_json in json.get('functions', []): 443 for function_json in json.get('functions', []):
497 function = Function(parent, 444 function = Function(parent,
498 function_json['name'], 445 function_json['name'],
499 function_json, 446 function_json,
500 namespace, 447 namespace,
501 Origin(from_json=True)) 448 Origin(from_json=True))
502 functions[function.name] = function 449 functions[function.name] = function
503 return functions 450 return functions
504 451
505
506 def _GetEvents(parent, json, namespace): 452 def _GetEvents(parent, json, namespace):
507 """Creates Function objects generated from the events in |json|. 453 """Creates Function objects generated from the events in |json|.
508 """ 454 """
509 events = OrderedDict() 455 events = OrderedDict()
510 for event_json in json.get('events', []): 456 for event_json in json.get('events', []):
511 event = Function(parent, 457 event = Function(parent,
512 event_json['name'], 458 event_json['name'],
513 event_json, 459 event_json,
514 namespace, 460 namespace,
515 Origin(from_client=True)) 461 Origin(from_client=True))
516 events[event.name] = event 462 events[event.name] = event
517 return events 463 return events
518 464
519
520 def _GetProperties(parent, json, namespace, origin): 465 def _GetProperties(parent, json, namespace, origin):
521 """Generates Property objects extracted from |json|. 466 """Generates Property objects extracted from |json|.
522 """ 467 """
523 properties = OrderedDict() 468 properties = OrderedDict()
524 for name, property_json in json.get('properties', {}).items(): 469 for name, property_json in json.get('properties', {}).items():
525 properties[name] = Property(parent, name, property_json, namespace, origin) 470 properties[name] = Property(parent, name, property_json, namespace, origin)
526 return properties 471 return properties
527 472
528
529 class _PlatformInfo(_Enum): 473 class _PlatformInfo(_Enum):
530 def __init__(self, name): 474 def __init__(self, name):
531 _Enum.__init__(self, name) 475 _Enum.__init__(self, name)
532 476
533
534 class Platforms(object): 477 class Platforms(object):
535 """Enum of the possible platforms. 478 """Enum of the possible platforms.
536 """ 479 """
537 CHROMEOS = _PlatformInfo("chromeos") 480 CHROMEOS = _PlatformInfo("chromeos")
538 CHROMEOS_TOUCH = _PlatformInfo("chromeos_touch") 481 CHROMEOS_TOUCH = _PlatformInfo("chromeos_touch")
539 LINUX = _PlatformInfo("linux") 482 LINUX = _PlatformInfo("linux")
540 MAC = _PlatformInfo("mac") 483 MAC = _PlatformInfo("mac")
541 WIN = _PlatformInfo("win") 484 WIN = _PlatformInfo("win")
542 485
543
544 def _GetPlatforms(json): 486 def _GetPlatforms(json):
545 if 'platforms' not in json: 487 if 'platforms' not in json:
546 return None 488 return None
547 platforms = [] 489 platforms = []
548 for platform_name in json['platforms']: 490 for platform_name in json['platforms']:
549 for platform_enum in _Enum.GetAll(Platforms): 491 for platform_enum in _Enum.GetAll(Platforms):
550 if platform_name == platform_enum.name: 492 if platform_name == platform_enum.name:
551 platforms.append(platform_enum) 493 platforms.append(platform_enum)
552 break 494 break
553 return platforms 495 return platforms
OLDNEW
« no previous file with comments | « trunk/src/tools/json_schema_compiler/features_h_generator.py ('k') | trunk/src/tools/json_schema_compiler/schema_loader.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698