def __init__(self, json5_file_paths): super(MakeQualifiedNamesWriter, self).__init__(None) self._input_files = copy.copy(json5_file_paths) assert len(json5_file_paths) <= 2, 'MakeQualifiedNamesWriter requires at most 2 in files, got %d.' % len(json5_file_paths) if len(json5_file_paths) == 2: self.tags_json5_file = Json5File.load_from_files( [json5_file_paths.pop(0)], self.default_metadata, self.default_parameters) else: self.tags_json5_file = None self.attrs_json5_file = Json5File.load_from_files([json5_file_paths.pop()], self.default_metadata, self.default_parameters) self.namespace = self._metadata('namespace') namespace_prefix = self._metadata('namespacePrefix') or self.namespace.lower() namespace_uri = self._metadata('namespaceURI') use_namespace_for_attrs = self.attrs_json5_file.metadata['attrsNullNamespace'] is None self._outputs = { (self.namespace + "Names.h"): self.generate_header, (self.namespace + "Names.cpp"): self.generate_implementation, } self._template_context = { 'attrs': self.attrs_json5_file.name_dictionaries, 'export': self._metadata('export'), 'input_files': self._input_files, 'namespace': self.namespace, 'namespace_prefix': namespace_prefix, 'namespace_uri': namespace_uri, 'tags': self.tags_json5_file.name_dictionaries if self.tags_json5_file else [], 'use_namespace_for_attrs': use_namespace_for_attrs, }
def __init__(self, json5_file_paths, output_dir): super(MakeQualifiedNamesWriter, self).__init__(None, output_dir) self._input_files = copy.copy(json5_file_paths) assert len(json5_file_paths) <= 3, 'MakeQualifiedNamesWriter requires at most 3 in files, got %d.' % len(json5_file_paths) # Input files are in a strict order with more optional files *first*: # 1) ARIA properties # 2) Tags # 3) Attributes if len(json5_file_paths) >= 3: aria_json5_filename = json5_file_paths.pop(0) self.aria_reader = ARIAReader(aria_json5_filename) else: self.aria_reader = None if len(json5_file_paths) >= 2: tags_json5_filename = json5_file_paths.pop(0) self.tags_json5_file = Json5File.load_from_files([tags_json5_filename], self.default_metadata, self.default_parameters) else: self.tags_json5_file = None self.attrs_json5_file = Json5File.load_from_files([json5_file_paths.pop()], self.default_metadata, self.default_parameters) if self.aria_reader is not None: self.attrs_json5_file.merge_from(self.aria_reader.attributes_list()) self.namespace = self._metadata('namespace') cpp_namespace = self.namespace.lower() + '_names' namespace_prefix = self._metadata('namespacePrefix') or 'k' # TODO(tkent): Remove the following branch. crbug.com/889726 if self.namespace in ('HTML', 'MathML', 'SVG'): cpp_namespace = self.namespace + 'Names' MakeQualifiedNamesWriter.filters['symbol'] = _legacy_symbol namespace_prefix = self._metadata('namespacePrefix') or self.namespace.lower() namespace_uri = self._metadata('namespaceURI') use_namespace_for_attrs = self.attrs_json5_file.metadata['attrsNullNamespace'] is None self._outputs = { (self.namespace.lower() + "_names.h"): self.generate_header, (self.namespace.lower() + "_names.cc"): self.generate_implementation, } qualified_header = self._relative_output_dir + self.namespace.lower() + '_names.h' self._template_context = { 'attrs': self.attrs_json5_file.name_dictionaries, 'cpp_namespace': cpp_namespace, 'export': self._metadata('export'), 'header_guard': self.make_header_guard(qualified_header), 'input_files': self._input_files, 'namespace': self.namespace, 'namespace_prefix': namespace_prefix, 'namespace_uri': namespace_uri, 'tags': self.tags_json5_file.name_dictionaries if self.tags_json5_file else [], 'this_include_path': qualified_header, 'use_namespace_for_attrs': use_namespace_for_attrs, }
def test_valid_dict_value_parse(self): actual = Json5File.load_from_files([self.path_of_test_file( 'json5_generator_valid_dict_value.json5')]).name_dictionaries expected = [ {'name': 'item1', 'param1': {'keys': 'valid', 'random': 'values'}}, {'name': 'item2', 'param1': {'random': 'values', 'default': 'valid'}} ] self.assertEqual(len(actual), len(expected)) for exp, act in zip(expected, actual): self.assertDictEqual(exp['param1'], act['param1'])
def make_runtime_features_dict(): input_filename = os.path.join(TEST_INPUT_DIRECTORY, 'runtime_enabled_features.json5') json5_file = Json5File.load_from_files([input_filename]) features_map = {} for feature in json5_file.name_dictionaries: features_map[str(feature['name'])] = { 'in_origin_trial': feature['in_origin_trial'] } return features_map
def __init__(self, json5_file_paths): super(CSSPropertyAPIWriter, self).__init__(json5_file_paths[0]) # TODO(aazzam): Move the logic for loading CSSPropertyAPIMethods.json5 into a new class APIMethodsWriter(). assert len(json5_file_paths) == 2,\ 'CSSPropertyAPIWriter requires 2 input json5 files files, got {}.'.format(len(json5_file_paths)) self.css_property_api_methods = Json5File.load_from_files( [json5_file_paths[1]], {}, {}) self._outputs = { 'CSSPropertyDescriptor.cpp': self.generate_property_descriptor_cpp, 'CSSPropertyDescriptor.h': self.generate_property_descriptor_h, 'CSSPropertyAPI.h': self.generate_property_api, } # Stores a map of API method name -> (return_type, parameters) self.all_api_methods = {} # Stores an ordered list of all API method names. This must match the # order they appear in the Descriptor object. self.ordered_api_method_names = [] for api_method in self.css_property_api_methods.name_dictionaries: self.ordered_api_method_names.append(api_method['name']) # TODO(shend): wrap description to 72 chars self.all_api_methods[api_method['name']] = ApiMethod( return_type=api_method['return_type'], parameters=api_method['parameters'], description=api_method['description'], ) # Temporary map of API classname to list of propertyIDs that the API class is for. properties_for_class = defaultdict(list) # Map of API classname to list of methods implemented by that class. self.methods_for_classes = defaultdict(list) for property_ in self.properties().values(): if property_['api_class'] is None: continue classname = get_classname(property_) properties_for_class[classname].append(property_['property_id']) # For api_classes that contain multiple properties, combine all implemented properties. # This list contains duplicate entries, but is only used to check if a method is # implemented for an api_class. self.methods_for_classes[classname] += property_['api_methods'] self._outputs[classname + '.h'] = self.generate_property_api_h_builder( classname) # Stores a list of classes with elements (index, classname, [propertyIDs, ..], [api_methods, ...]). self._api_classes = [] for i, classname in enumerate(properties_for_class.keys()): self._api_classes.append( ApiClass( index=i + 1, classname=classname, property_ids=properties_for_class[classname], methods_for_class=self.methods_for_classes[classname]))
def __init__(self, json5_file_paths): super(CSSPropertyAPIWriter, self).__init__([json5_file_paths[0]]) # TODO(aazzam): Move the logic for loading CSSPropertyAPIMethods.json5 into a new class APIMethodsWriter(). assert len(json5_file_paths) == 2,\ 'CSSPropertyAPIWriter requires 2 input json5 files files, got {}.'.format(len(json5_file_paths)) self.css_property_api_methods = Json5File.load_from_files( [json5_file_paths[1]]) self._outputs = { 'CSSPropertyDescriptor.cpp': self.generate_property_descriptor_cpp, 'CSSPropertyDescriptor.h': self.generate_property_descriptor_h, } # Stores a map of API method name -> (return_type, parameters) self.all_api_methods = {} # Stores an ordered list of all API method names. This must match the # order they appear in the Descriptor object. self.ordered_api_method_names = [] for api_method in self.css_property_api_methods.name_dictionaries: self.ordered_api_method_names.append(api_method['name']) # TODO(shend): wrap description to 72 chars self.all_api_methods[api_method['name']] = ApiMethod( return_type=api_method['return_type'], parameters=api_method['parameters'], description=api_method['description'], ) # Temporary maps of API classname to list of propertyIDs and corresponding # enum values that the API class is for. properties_for_class = defaultdict(list) property_enums_for_class = defaultdict(list) # Map of API classname to list of methods implemented by that class. self.methods_for_classes = defaultdict(list) for property_ in self.properties().values(): if property_['api_class'] is None: continue classname = get_classname(property_) properties_for_class[classname].append(property_['property_id']) property_enums_for_class[classname].append(property_['enum_value']) # For api_classes that contain multiple properties, combine all implemented properties. # This list contains duplicate entries, but is only used to check if a method is # implemented for an api_class. self.methods_for_classes[classname] += property_['api_methods'] self._outputs[classname + '.h'] = self.generate_property_api_h_builder( classname, property_['name']) # Stores a list of classes with elements (index, classname, [propertyIDs, ..], [api_methods, ...]). self._api_classes = [] for i, classname in enumerate(properties_for_class.keys()): self._api_classes.append( ApiClass( index=i + 1, classname=classname, property_ids=properties_for_class[classname], methods_for_class=self.methods_for_classes[classname])) # Build a table converting id (including aliases) to api class descriptors self._invalid_descriptor_index = 0 # Initialize the whole thing to the invalid descriptor to handle gaps num_indices = self.last_unresolved_property_id + 1 self._descriptor_indices = dict.fromkeys(xrange(num_indices), { 'id': self._invalid_descriptor_index, 'api': None }) # Now populate all entries for which there exists a class, i.e. that aren't gaps for api_class in self._api_classes: for property_enum in property_enums_for_class[api_class.classname]: self._descriptor_indices[property_enum] = { 'id': api_class.index, 'api': api_class.classname }
def test_key_not_in_valid_keys(self): with self.assertRaises(Exception): Json5File.load_from_files([self.path_of_test_file('json5_generator_invalid_key.json5')])
def test_no_valid_keys(self): with self.assertRaises(AssertionError): Json5File.load_from_files([self.path_of_test_file('json5_generator_no_valid_keys.json5')])