summaryrefslogtreecommitdiffstats
path: root/tools/json_schema_compiler
diff options
context:
space:
mode:
authormitchellwrosen@chromium.org <mitchellwrosen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-31 22:47:50 +0000
committermitchellwrosen@chromium.org <mitchellwrosen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-31 22:47:50 +0000
commit1d0f57e1473a43c653d9f7afb8a81435ed0bdfa8 (patch)
tree21bc3582153fbe5002fbca466181512c064f2240 /tools/json_schema_compiler
parent0933b60eecd7c538e7833331bdf665aff2a4490a (diff)
downloadchromium_src-1d0f57e1473a43c653d9f7afb8a81435ed0bdfa8.zip
chromium_src-1d0f57e1473a43c653d9f7afb8a81435ed0bdfa8.tar.gz
chromium_src-1d0f57e1473a43c653d9f7afb8a81435ed0bdfa8.tar.bz2
Added JSON schema compiler support for serialized types
Currently supports string->int, string->int64, and int->string. BUG=139076 Review URL: https://chromiumcodereview.appspot.com/10825029 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@149302 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools/json_schema_compiler')
-rw-r--r--tools/json_schema_compiler/cc_generator.py83
-rw-r--r--tools/json_schema_compiler/cpp_type_generator.py44
-rwxr-xr-xtools/json_schema_compiler/cpp_type_generator_test.py11
-rw-r--r--tools/json_schema_compiler/cpp_util.py48
-rw-r--r--tools/json_schema_compiler/h_generator.py12
-rw-r--r--tools/json_schema_compiler/model.py53
-rwxr-xr-xtools/json_schema_compiler/model_test.py2
7 files changed, 190 insertions, 63 deletions
diff --git a/tools/json_schema_compiler/cc_generator.py b/tools/json_schema_compiler/cc_generator.py
index c7465651..6875187 100644
--- a/tools/json_schema_compiler/cc_generator.py
+++ b/tools/json_schema_compiler/cc_generator.py
@@ -253,20 +253,36 @@ class CCGenerator(object):
else:
if prop.optional:
if prop.type_ == PropertyType.ENUM:
- c.Sblock('if (%s != %s)' %
+ c.Sblock('if (%s != %s) {' %
(prop.unix_name,
self._cpp_type_generator.GetEnumNoneValue(prop)))
elif prop.type_ == PropertyType.CHOICES:
- c.Sblock('if (%s_type != %s)' %
+ c.Sblock('if (%s_type != %s) {' %
(prop.unix_name,
self._cpp_type_generator.GetEnumNoneValue(prop)))
else:
- c.Sblock('if (%s.get())' % prop.unix_name)
- c.Append('value->SetWithoutPathExpansion("%s", %s);' % (
- prop.name,
- self._CreateValueFromProperty(prop, 'this->' + prop.unix_name)))
+ c.Sblock('if (%s.get()) {' % prop.unix_name)
+
+ if prop.type_ == prop.compiled_type:
+ c.Append('value->SetWithoutPathExpansion("%s", %s);' % (
+ prop.name,
+ self._CreateValueFromProperty(prop, 'this->' + prop.unix_name)))
+ else:
+ conversion_src = 'this->' + prop.unix_name
+ if prop.optional:
+ conversion_src = '*' + conversion_src
+ (c.Append('%s %s;' % (self._cpp_type_generator.GetType(prop),
+ prop.unix_name))
+ .Append(cpp_util.GenerateCompiledTypeToTypeConversion(
+ self._cpp_type_generator.GetReferencedProperty(prop),
+ conversion_src,
+ prop.unix_name) + ';')
+ .Append('value->SetWithoutPathExpansion("%s", %s);' % (
+ prop.unix_name,
+ self._CreateValueFromProperty(prop, prop.unix_name)))
+ )
if prop.optional:
- c.Eblock();
+ c.Eblock('}');
(c.Append()
.Append('return value.Pass();')
.Eblock('}')
@@ -337,7 +353,11 @@ class CCGenerator(object):
self._cpp_type_generator.GetReferencedProperty(prop), var,
prop.optional)
elif self._IsFundamentalOrFundamentalRef(prop):
- if prop.optional:
+ # If prop.type != prop.compiled_type, then no asterisk is necessary
+ # because the target is a local variable and not a dereferenced scoped
+ # pointer. The asterisk is instead prepended to conversion_src around line
+ # 273.
+ if prop.optional and prop.type_ == prop.compiled_type:
var = '*' + var
prop = self._cpp_type_generator.GetReferencedProperty(prop);
return {
@@ -448,16 +468,42 @@ class CCGenerator(object):
value_var,
'&temp'))
.Append(' return %(failure_value)s;')
- .Append('%(dst)s->%(name)s.reset(new %(ctype)s(temp));')
)
+ if prop.type_ != prop.compiled_type:
+ (c.Append('%(compiled_ctype)s temp2;')
+ .Append('if (!%s)' %
+ cpp_util.GenerateTypeToCompiledTypeConversion(
+ self._cpp_type_generator.GetReferencedProperty(prop),
+ 'temp',
+ 'temp2'))
+ .Append(' return %(failure_value)s;')
+ .Append('%(dst)s->%(name)s.reset(new %(compiled_ctype)s(temp2));')
+ )
+ else:
+ c.Append('%(dst)s->%(name)s.reset(new %(ctype)s(temp));')
+
else:
+ if prop.type_ == prop.compiled_type:
+ assignment_target = '&%s->%s' % (dst, prop.unix_name)
+ else:
+ c.Append('%(ctype)s temp;')
+ assignment_target = '&temp'
(c.Append('if (!%s)' %
cpp_util.GetAsFundamentalValue(
self._cpp_type_generator.GetReferencedProperty(prop),
value_var,
- '&%s->%s' % (dst, prop.unix_name)))
+ assignment_target))
.Append(' return %(failure_value)s;')
)
+ if prop.type_ != prop.compiled_type:
+ (c.Append('if (!%s)' %
+ cpp_util.GenerateTypeToCompiledTypeConversion(
+ self._cpp_type_generator.GetReferencedProperty(prop),
+ 'temp',
+ '%s->%s' % (dst, prop.unix_name)))
+ .Append(' return %(failure_value)s;')
+ )
+
elif self._IsObjectOrObjectRef(prop):
if prop.optional:
(c.Append('const base::DictionaryValue* dictionary = NULL;')
@@ -546,6 +592,7 @@ class CCGenerator(object):
}
if prop.type_ not in (PropertyType.CHOICES, PropertyType.ANY):
sub['ctype'] = self._cpp_type_generator.GetType(prop)
+ sub['compiled_ctype'] = self._cpp_type_generator.GetCompiledType(prop)
sub['value_type'] = cpp_util.GetValueType(self._cpp_type_generator
.GetReferencedProperty(prop).type_)
c.Substitute(sub)
@@ -721,10 +768,20 @@ class CCGenerator(object):
# scoped_ptr if it's optional.
param_copy = param.Copy()
param_copy.optional = False
- c.Append('create_results->Append(%s);' %
- self._CreateValueFromProperty(param_copy, param_copy.unix_name))
declaration_list.append("const %s" % cpp_util.GetParameterDeclaration(
- param_copy, self._cpp_type_generator.GetType(param_copy)))
+ param_copy, self._cpp_type_generator.GetCompiledType(param_copy)))
+ param_name = param_copy.unix_name
+ if param_copy.type_ != param_copy.compiled_type:
+ param_name = 'temp_' + param_name
+ (c.Append('%s %s;' % (self._cpp_type_generator.GetType(param_copy),
+ param_name))
+ .Append(cpp_util.GenerateCompiledTypeToTypeConversion(
+ param_copy,
+ param_copy.unix_name,
+ param_name) + ';')
+ )
+ c.Append('create_results->Append(%s);' %
+ self._CreateValueFromProperty(param_copy, param_name))
c.Append('return create_results.Pass();')
c.Eblock('}')
diff --git a/tools/json_schema_compiler/cpp_type_generator.py b/tools/json_schema_compiler/cpp_type_generator.py
index a305b75..a0f5752 100644
--- a/tools/json_schema_compiler/cpp_type_generator.py
+++ b/tools/json_schema_compiler/cpp_type_generator.py
@@ -116,6 +116,14 @@ class CppTypeGenerator(object):
return cpp_util.Classname(prop.name) + 'Type'
def GetType(self, prop, pad_for_generics=False, wrap_optional=False):
+ return self._GetTypeHelper(prop, pad_for_generics, wrap_optional)
+
+ def GetCompiledType(self, prop, pad_for_generics=False, wrap_optional=False):
+ return self._GetTypeHelper(prop, pad_for_generics, wrap_optional,
+ use_compiled_type=True)
+
+ def _GetTypeHelper(self, prop, pad_for_generics=False, wrap_optional=False,
+ use_compiled_type=False):
"""Translates a model.Property into its C++ type.
If REF types from different namespaces are referenced, will resolve
@@ -125,9 +133,13 @@ class CppTypeGenerator(object):
Use wrap_optional to wrap the type in a scoped_ptr<T> if the Property is
optional.
+
+ Use use_compiled_type when converting from prop.type_ to prop.compiled_type.
"""
cpp_type = None
- if prop.type_ == PropertyType.REF:
+ type_ = prop.type_ if not use_compiled_type else prop.compiled_type
+
+ if type_ == PropertyType.REF:
dependency_namespace = self._ResolveTypeNamespace(prop.ref_type)
if not dependency_namespace:
raise KeyError('Cannot find referenced type: %s' % prop.ref_type)
@@ -136,28 +148,30 @@ class CppTypeGenerator(object):
schema_util.StripSchemaNamespace(prop.ref_type))
else:
cpp_type = schema_util.StripSchemaNamespace(prop.ref_type)
- elif prop.type_ == PropertyType.BOOLEAN:
+ elif type_ == PropertyType.BOOLEAN:
cpp_type = 'bool'
- elif prop.type_ == PropertyType.INTEGER:
+ elif type_ == PropertyType.INTEGER:
cpp_type = 'int'
- elif prop.type_ == PropertyType.DOUBLE:
+ elif type_ == PropertyType.INT64:
+ cpp_type = 'int64'
+ elif type_ == PropertyType.DOUBLE:
cpp_type = 'double'
- elif prop.type_ == PropertyType.STRING:
+ elif type_ == PropertyType.STRING:
cpp_type = 'std::string'
- elif prop.type_ == PropertyType.ENUM:
+ elif type_ == PropertyType.ENUM:
cpp_type = cpp_util.Classname(prop.name)
- elif prop.type_ == PropertyType.ADDITIONAL_PROPERTIES:
+ elif type_ == PropertyType.ADDITIONAL_PROPERTIES:
cpp_type = 'base::DictionaryValue'
- elif prop.type_ == PropertyType.ANY:
+ elif type_ == PropertyType.ANY:
cpp_type = any_helper.ANY_CLASS
- elif prop.type_ == PropertyType.OBJECT:
+ elif type_ == PropertyType.OBJECT:
cpp_type = cpp_util.Classname(prop.name)
- elif prop.type_ == PropertyType.FUNCTION:
+ elif type_ == PropertyType.FUNCTION:
# Functions come into the json schema compiler as empty objects. We can
# record these as empty DictionaryValue's so that we know if the function
# was passed in or not.
cpp_type = 'base::DictionaryValue'
- elif prop.type_ == PropertyType.ARRAY:
+ elif type_ == PropertyType.ARRAY:
item_type = prop.item_type
if item_type.type_ == PropertyType.REF:
item_type = self.GetReferencedProperty(item_type)
@@ -168,14 +182,14 @@ class CppTypeGenerator(object):
cpp_type = 'std::vector<%s> '
cpp_type = cpp_type % self.GetType(
prop.item_type, pad_for_generics=True)
- elif prop.type_ == PropertyType.BINARY:
+ elif type_ == PropertyType.BINARY:
cpp_type = 'std::string'
else:
- raise NotImplementedError(prop.type_)
+ raise NotImplementedError(type_)
# Enums aren't wrapped because C++ won't allow it. Optional enums have a
# NONE value generated instead.
- if wrap_optional and prop.optional and prop.type_ != PropertyType.ENUM:
+ if wrap_optional and prop.optional and type_ != PropertyType.ENUM:
cpp_type = 'scoped_ptr<%s> ' % cpp_type
if pad_for_generics:
return cpp_type
@@ -222,6 +236,8 @@ class CppTypeGenerator(object):
self._cpp_namespaces[dependency])
for dependency in self._NamespaceTypeDependencies().keys()]):
c.Append('#include "%s"' % header)
+ c.Append('#include "base/string_number_conversions.h"')
+
if self._namespace.events:
c.Append('#include "base/json/json_writer.h"')
return c
diff --git a/tools/json_schema_compiler/cpp_type_generator_test.py b/tools/json_schema_compiler/cpp_type_generator_test.py
index 17b501e..decf1e9 100755
--- a/tools/json_schema_compiler/cpp_type_generator_test.py
+++ b/tools/json_schema_compiler/cpp_type_generator_test.py
@@ -48,6 +48,7 @@ class CppTypeGeneratorTest(unittest.TestCase):
manager = CppTypeGenerator('', self.windows, self.windows.unix_name)
manager.AddNamespace(self.tabs, self.tabs.unix_name)
self.assertEquals('#include "path/to/tabs.h"\n'
+ '#include "base/string_number_conversions.h"\n'
'#include "base/json/json_writer.h"',
manager.GenerateIncludes().Render())
self.assertEquals('namespace tabs {\n'
@@ -58,7 +59,8 @@ class CppTypeGeneratorTest(unittest.TestCase):
'} // windows',
manager.GenerateForwardDeclarations().Render())
manager = CppTypeGenerator('', self.permissions, self.permissions.unix_name)
- self.assertEquals('#include "base/json/json_writer.h"',
+ self.assertEquals('#include "base/string_number_conversions.h"\n'
+ '#include "base/json/json_writer.h"',
manager.GenerateIncludes().Render())
self.assertEquals('namespace permissions {\n'
'struct Permissions;\n'
@@ -66,7 +68,8 @@ class CppTypeGeneratorTest(unittest.TestCase):
manager.GenerateForwardDeclarations().Render())
manager = CppTypeGenerator('', self.content_settings,
self.content_settings.unix_name)
- self.assertEquals('', manager.GenerateIncludes().Render())
+ self.assertEquals('#include "base/string_number_conversions.h"',
+ manager.GenerateIncludes().Render())
def testGenerateIncludesAndForwardDeclarationsMultipleTypes(self):
@@ -83,6 +86,7 @@ class CppTypeGeneratorTest(unittest.TestCase):
manager = CppTypeGenerator('', windows, self.windows.unix_name)
manager.AddNamespace(tabs_namespace, self.tabs.unix_name)
self.assertEquals('#include "path/to/tabs.h"\n'
+ '#include "base/string_number_conversions.h"\n'
'#include "base/json/json_writer.h"',
manager.GenerateIncludes().Render())
self.assertEquals('namespace tabs {\n'
@@ -109,7 +113,8 @@ class CppTypeGeneratorTest(unittest.TestCase):
manager.AddNamespace(browser_action_namespace,
self.browser_action.unix_name)
self.assertEquals('#include "path/to/browser_action.h"\n'
- '#include "path/to/font_settings.h"',
+ '#include "path/to/font_settings.h"\n'
+ '#include "base/string_number_conversions.h"',
manager.GenerateIncludes().Render())
self.assertEquals('namespace browserAction {\n'
'typedef std::vector<int> ColorArray;\n'
diff --git a/tools/json_schema_compiler/cpp_util.py b/tools/json_schema_compiler/cpp_util.py
index 1229fb8..96a5cd3 100644
--- a/tools/json_schema_compiler/cpp_util.py
+++ b/tools/json_schema_compiler/cpp_util.py
@@ -75,9 +75,47 @@ def GetParameterDeclaration(param, type_):
}
def GenerateIfndefName(path, filename):
- """Formats a path and filename as a #define name.
+ """Formats a path and filename as a #define name.
- e.g chrome/extensions/gen, file.h becomes CHROME_EXTENSIONS_GEN_FILE_H__.
- """
- return (('%s_%s_H__' % (path, filename))
- .upper().replace(os.sep, '_').replace('/', '_'))
+ e.g chrome/extensions/gen, file.h becomes CHROME_EXTENSIONS_GEN_FILE_H__.
+ """
+ return (('%s_%s_H__' % (path, filename))
+ .upper().replace(os.sep, '_').replace('/', '_'))
+
+def GenerateTypeToCompiledTypeConversion(prop, from_, to):
+ try:
+ return _GenerateTypeConversionHelper(prop.type_, prop.compiled_type, from_,
+ to)
+ except KeyError:
+ raise NotImplementedError('Conversion from %s to %s in %s not supported' %
+ (prop.type_, prop.compiled_type, prop.name))
+
+def GenerateCompiledTypeToTypeConversion(prop, from_, to):
+ try:
+ return _GenerateTypeConversionHelper(prop.compiled_type, prop.type_, from_,
+ to)
+ except KeyError:
+ raise NotImplementedError('Conversion from %s to %s in %s not supported' %
+ (prop.compiled_type, prop.type_, prop.name))
+
+def _GenerateTypeConversionHelper(from_type, to_type, from_, to):
+ """Converts from PropertyType from_type to PropertyType to_type.
+
+ from_type: The PropertyType to be converted from.
+ to_type: The PropertyType to be converted to.
+ from_: The variable name of the type to be converted from.
+ to: The variable name of the type to be converted to.
+ """
+ # TODO(mwrosen): Add support for more from/to combinations as necessary.
+ return {
+ PropertyType.STRING: {
+ PropertyType.INTEGER: 'base::StringToInt(%(from)s, &%(to)s)',
+ PropertyType.INT64: 'base::StringToInt64(%(from)s, &%(to)s)',
+ },
+ PropertyType.INTEGER: {
+ PropertyType.STRING: '%(to)s = base::IntToString(%(from)s)',
+ },
+ PropertyType.INT64: {
+ PropertyType.STRING: '%(to)s = base::Int64ToString(%(from)s)',
+ }
+ }[from_type][to_type] % {'from': from_, 'to': to}
diff --git a/tools/json_schema_compiler/h_generator.py b/tools/json_schema_compiler/h_generator.py
index 03879ca..e1d9f48 100644
--- a/tools/json_schema_compiler/h_generator.py
+++ b/tools/json_schema_compiler/h_generator.py
@@ -159,8 +159,8 @@ class HGenerator(object):
if prop.description:
c.Comment(prop.description)
(c.Append('%s %s;' % (
- self._cpp_type_generator.GetType(prop, wrap_optional=True),
- prop.unix_name))
+ self._cpp_type_generator.GetCompiledType(prop, wrap_optional=True),
+ prop.unix_name))
.Append()
)
return c
@@ -183,8 +183,8 @@ class HGenerator(object):
c.Comment(type_.description)
c.Append('typedef std::vector<%(item_type)s> %(classname)s;')
c.Substitute({'classname': classname, 'item_type':
- self._cpp_type_generator.GetType(type_.item_type,
- wrap_optional=True)})
+ self._cpp_type_generator.GetCompiledType(type_.item_type,
+ wrap_optional=True)})
elif type_.type_ == PropertyType.STRING:
if type_.description:
c.Comment(type_.description)
@@ -294,7 +294,7 @@ class HGenerator(object):
[choice.type_.name for choice in prop.choices.values()]))
c.Concat(self._GeneratePropertyStructures(prop.choices.values()))
elif prop.type_ == PropertyType.ENUM:
- enum_name = self._cpp_type_generator.GetType(prop)
+ enum_name = self._cpp_type_generator.GetCompiledType(prop)
c.Concat(self._GenerateEnumDeclaration(
enum_name,
prop,
@@ -339,7 +339,7 @@ class HGenerator(object):
if param.description:
c.Comment(param.description)
declaration_list.append('const %s' % cpp_util.GetParameterDeclaration(
- param, self._cpp_type_generator.GetType(param)))
+ param, self._cpp_type_generator.GetCompiledType(param)))
c.Append('scoped_ptr<base::ListValue> Create(%s);' %
', '.join(declaration_list))
if generate_to_json:
diff --git a/tools/json_schema_compiler/model.py b/tools/json_schema_compiler/model.py
index 4de04c4..b7a094a5 100644
--- a/tools/json_schema_compiler/model.py
+++ b/tools/json_schema_compiler/model.py
@@ -151,6 +151,8 @@ class Property(object):
- |optional| a boolean representing whether the property is optional
- |description| a description of the property (if provided)
- |type_| the model.PropertyType of this property
+ - |compiled_type| the model.PropertyType that this property should be
+ compiled to from the JSON. Defaults to |type_|.
- |ref_type| the type that the REF property is referencing. Can be used to
map to its model.Type
- |item_type| a model.Property representing the type of each element in an
@@ -190,40 +192,23 @@ class Property(object):
self.enum_values.append(value)
self.type_ = PropertyType.ENUM
elif 'type' in json:
- json_type = json['type']
- if json_type == 'string':
- self.type_ = PropertyType.STRING
- elif json_type == 'any':
- self.type_ = PropertyType.ANY
- elif json_type == 'boolean':
- self.type_ = PropertyType.BOOLEAN
- elif json_type == 'integer':
- self.type_ = PropertyType.INTEGER
- elif json_type == 'number':
- self.type_ = PropertyType.DOUBLE
- elif json_type == 'array':
+ self.type_ = self._JsonTypeToPropertyType(json['type'])
+ if self.type_ == PropertyType.ARRAY:
self.item_type = Property(self, name + "Element", json['items'],
from_json=from_json,
from_client=from_client)
- self.type_ = PropertyType.ARRAY
- elif json_type == 'object':
- self.type_ = PropertyType.OBJECT
+ elif self.type_ == PropertyType.OBJECT:
# These members are read when this OBJECT Property is used as a Type
type_ = Type(self, self.name, json)
# self.properties will already have some value from |_AddProperties|.
self.properties.update(type_.properties)
self.functions = type_.functions
- elif json_type == 'function':
- self.type_ = PropertyType.FUNCTION
- elif json_type == 'binary':
- self.type_ = PropertyType.BINARY
- else:
- raise ParseException(self, 'type ' + json_type + ' not recognized')
elif 'choices' in json:
if not json['choices'] or len(json['choices']) == 0:
raise ParseException(self, 'Choices has no choices')
self.choices = {}
self.type_ = PropertyType.CHOICES
+ self.compiled_type = self.type_
for choice_json in json['choices']:
choice = Property(self, self.name, choice_json,
from_json=from_json,
@@ -237,6 +222,7 @@ class Property(object):
self.value = json['value']
if type(self.value) == int:
self.type_ = PropertyType.INTEGER
+ self.compiled_type = self.type_
else:
# TODO(kalman): support more types as necessary.
raise ParseException(
@@ -244,6 +230,30 @@ class Property(object):
else:
raise ParseException(
self, 'Property has no type, $ref, choices, or value')
+ if 'compiled_type' in json:
+ if 'type' in json:
+ self.compiled_type = self._JsonTypeToPropertyType(json['compiled_type'])
+ else:
+ raise ParseException(self, 'Property has compiled_type but no type')
+ else:
+ self.compiled_type = self.type_
+
+ def _JsonTypeToPropertyType(self, json_type):
+ try:
+ return {
+ 'any': PropertyType.ANY,
+ 'array': PropertyType.ARRAY,
+ 'binary': PropertyType.BINARY,
+ 'boolean': PropertyType.BOOLEAN,
+ 'integer': PropertyType.INTEGER,
+ 'int64': PropertyType.INT64,
+ 'function': PropertyType.FUNCTION,
+ 'number': PropertyType.DOUBLE,
+ 'object': PropertyType.OBJECT,
+ 'string': PropertyType.STRING,
+ }[json_type]
+ except KeyError:
+ raise NotImplementedError('Type %s not recognized' % json_type)
def GetUnixName(self):
"""Gets the property's unix_name. Raises AttributeError if not set.
@@ -288,6 +298,7 @@ class PropertyType(object):
return self.name
INTEGER = _Info(True, "INTEGER")
+ INT64 = _Info(True, "INT64")
DOUBLE = _Info(True, "DOUBLE")
BOOLEAN = _Info(True, "BOOLEAN")
STRING = _Info(True, "STRING")
diff --git a/tools/json_schema_compiler/model_test.py b/tools/json_schema_compiler/model_test.py
index 880ae8d..8cd43e8 100755
--- a/tools/json_schema_compiler/model_test.py
+++ b/tools/json_schema_compiler/model_test.py
@@ -66,7 +66,7 @@ class ModelTest(unittest.TestCase):
def testPropertyNotImplemented(self):
(self.permissions_json[0]['types'][0]
['properties']['permissions']['type']) = 'something'
- self.assertRaises(model.ParseException, self.model.AddNamespace,
+ self.assertRaises(NotImplementedError, self.model.AddNamespace,
self.permissions_json[0], 'path/to/something.json')
def testDescription(self):