def parse(cls, filename, search_paths=None, skip_disabled_mappings=False): search_paths = search_paths or [] data = load_json_from_search_path(filename, search_paths) # Flatten all parent files into one dict while len(data.get('parents', [])) > 0: for parent_filename in data.get('parents', []): parent_data = load_json_from_search_path( parent_filename, search_paths) # Merge data *into* parents, so we keep any overrides data = merge(parent_data, data) data['parents'].remove(parent_filename) message_set = cls(data.get('name', 'generic')) message_set.initializers = data.get('initializers', []) message_set.loopers = data.get('loopers', []) message_set.buses = cls._parse_buses(data) message_set.bit_numbering_inverted = data.get('bit_numbering_inverted', None) message_set.extra_sources = set(data.get('extra_sources', set())) mapping_config = message_set._parse_mappings(data, search_paths, skip_disabled_mappings) message_set.initializers.extend(mapping_config['initializers']) message_set.loopers.extend(mapping_config['loopers']) message_set.extra_sources.update(mapping_config['extra_sources']) # TODO could we parse the top level config file as if it were a mapping # and avoid duplicating this code? for message_id, message in list(data.get('messages', {}).items()): message['id'] = message_id mapping_config['messages'].append(message) mapping_config['diagnostic_messages'].extend( data.get('diagnostic_messages', [])) message_set.diagnostic_messages = cls._parse_diagnostic_messages( message_set, mapping_config['diagnostic_messages']) mapping_config['commands'].extend(data.get('commands', [])) message_set.commands = cls._parse_commands(mapping_config['commands']) message_set._parse_messages(mapping_config['messages']) return message_set
def parse(cls, filename, search_paths=None, skip_disabled_mappings=False): search_paths = search_paths or [] data = load_json_from_search_path(filename, search_paths) # Flatten all parent files into one dict while len(data.get('parents', [])) > 0: for parent_filename in data.get('parents', []): parent_data = load_json_from_search_path(parent_filename, search_paths) # Merge data *into* parents, so we keep any overrides data = merge(parent_data, data) data['parents'].remove(parent_filename) message_set = cls(data.get('name', 'generic')) message_set.initializers = data.get('initializers', []) message_set.loopers = data.get('loopers', []) message_set.buses = cls._parse_buses(data) message_set.bit_numbering_inverted = data.get( 'bit_numbering_inverted', None) message_set.extra_sources = set(data.get('extra_sources', set())) mapping_config = message_set._parse_mappings(data, search_paths, skip_disabled_mappings) message_set.initializers.extend(mapping_config['initializers']) message_set.loopers.extend(mapping_config['loopers']) message_set.extra_sources.update(mapping_config['extra_sources']) # TODO could we parse the top level config file as if it were a mapping # and avoid duplicating this code? for message_id, message in data.get('messages', {}).items(): message['id'] = message_id mapping_config['messages'].append(message) mapping_config['diagnostic_messages'].extend(data.get('diagnostic_messages', [])) message_set.diagnostic_messages = cls._parse_diagnostic_messages( message_set, mapping_config['diagnostic_messages']) mapping_config['commands'].extend(data.get('commands', [])) message_set.commands = cls._parse_commands(mapping_config['commands']) message_set._parse_messages(mapping_config['messages']) return message_set
def _parse_mappings(self, data, search_paths, skip_disabled_mappings): all_messages = [] all_diagnostic_messages = [] all_commands = [] all_extra_sources = set() all_initializers = [] all_loopers = [] for mapping in data.get('mappings', []): if 'mapping' not in mapping: fatal_error("Mapping is missing the mapping file path") mapping_enabled = mapping.get('enabled', True) if not mapping_enabled: LOG.warning("Mapping '%s' is disabled" % mapping['mapping']) if skip_disabled_mappings: continue LOG.warning("Adding mapping '%s'" % mapping['mapping']) bus_name = mapping.get('bus', None) if bus_name is None: LOG.warning("No default bus associated with '%s' mapping" % mapping['mapping']) elif bus_name not in self.buses: fatal_error("Bus '%s' (from mapping %s) is not defined" % (bus_name, mapping['mapping'])) elif not self.buses[bus_name].valid(): LOG.warning("Mapping '%s' is disabled because bus '%s' " % (mapping['mapping'], bus_name) + "is not associated with a CAN controller") mapping['enabled'] = False if skip_disabled_mappings: continue mapping_data = load_json_from_search_path(mapping['mapping'], search_paths) commands = mapping_data.get('commands', []) for command in commands: command.setdefault('enabled', mapping_enabled) all_commands.extend(commands) diagnostic_messages = mapping_data.get('diagnostic_messages', []) for message in diagnostic_messages: message.setdefault('bus', bus_name) message.setdefault('enabled', mapping_enabled) all_diagnostic_messages.extend(diagnostic_messages) if mapping_enabled: all_initializers.extend(mapping_data.get('initializers', [])) all_loopers.extend(mapping_data.get('loopers', [])) all_extra_sources.update( set(mapping_data.get('extra_sources', set()))) messages = mapping_data.get('messages', {}) if len(messages) == 0: LOG.warning("Mapping file '%s' doesn't define any messages" % mapping['mapping']) if 'database' in mapping: database_filename, database_tree = self._parse_database( find_file(mapping['database'], search_paths)) messages = merge( merge_database_into_mapping(database_filename, database_tree, messages).get('messages', {}), messages) if mapping.get('bit_numbering_inverted', None) is None: LOG.warning( "The bit number inversion setting is undefined " "for the mapping '%s', but it " % mapping['mapping'] + "is database-backed - assuming inverted") for message in list(messages.values()): message.setdefault('bit_numbering_inverted', True) for message_id, message in list(messages.items()): message['id'] = message_id message.setdefault('bus', bus_name) message.setdefault('enabled', mapping_enabled) all_messages.extend(list(messages.values())) return { 'messages': all_messages, 'commands': all_commands, 'diagnostic_messages': all_diagnostic_messages, 'initializers': all_initializers, 'extra_sources': all_extra_sources, 'loopers': all_loopers }
def _parse_mappings(self, data, search_paths, skip_disabled_mappings): all_messages = [] all_commands = [] all_extra_sources = set() all_initializers = [] all_loopers = [] for mapping in data.get('mappings', []): if 'mapping' not in mapping: fatal_error("Mapping is missing the mapping file path") mapping_enabled = mapping.get('enabled', True) if not mapping_enabled: LOG.warning("Mapping '%s' is disabled" % mapping['mapping']) if skip_disabled_mappings: continue LOG.warning("Adding mapping '%s'" % mapping['mapping']) bus_name = mapping.get('bus', None) if bus_name is None: LOG.warning("No default bus associated with '%s' mapping" % mapping['mapping']) elif bus_name not in self.buses: fatal_error("Bus '%s' (from mapping %s) is not defined" % (bus_name, mapping['mapping'])) elif not self.buses[bus_name].valid(): LOG.warning("Mapping '%s' is disabled because bus '%s' " % ( mapping['mapping'], bus_name) + "is not associated with a CAN controller") mapping['enabled'] = False if skip_disabled_mappings: continue mapping_data = load_json_from_search_path(mapping['mapping'], search_paths) commands = mapping_data.get('commands', []) if not mapping_enabled: for command in commands: command['enabled'] = False all_commands.extend(commands) if mapping_enabled: all_initializers.extend(mapping_data.get('initializers', [])) all_loopers.extend(mapping_data.get('loopers', [])) all_extra_sources.update( set(mapping_data.get('extra_sources', set()))) messages = mapping_data.get('messages', {}) if len(messages) == 0: LOG.warning("Mapping file '%s' doesn't define any messages" % mapping['mapping']) if 'database' in mapping: database_filename, database_tree = self._parse_database( find_file(mapping['database'], search_paths)) messages = merge(merge_database_into_mapping(database_filename, database_tree, messages).get('messages', {}), messages) if mapping.get('bit_numbering_inverted', None) is None: LOG.warning("The bit number inversion setting is undefined " "for the mapping '%s', but it " % mapping['mapping'] + "is database-backed - assuming inverted") for message in messages.values(): message.setdefault('bit_numbering_inverted', True) for message_id, message in messages.items(): message['id'] = message_id message.setdefault('bus', bus_name) message.setdefault('enabled', mapping_enabled) all_messages.extend(messages.values()) return {'messages': all_messages, 'commands': all_commands, 'initializers': all_initializers, 'extra_sources': all_extra_sources, 'loopers': all_loopers}
def _parse_mappings(self, data, search_paths, skip_disabled_mappings): all_messages = [] all_commands = [] all_extra_sources = set() all_initializers = [] all_loopers = [] for mapping in data.get('mappings', []): if 'mapping' not in mapping: fatal_error("Mapping is missing the mapping file path") mapping_enabled = mapping.get('enabled', True) if not mapping_enabled: LOG.warning("Mapping '%s' is disabled" % mapping['mapping']) if skip_disabled_mappings: continue bus_name = mapping.get('bus', None) if bus_name is None: LOG.warning("No default bus associated with '%s' mapping" % mapping['mapping']) elif bus_name not in self.buses: fatal_error("Bus '%s' (from mapping %s) is not defined" % (bus_name, mapping['mapping'])) mapping_data = load_json_from_search_path(mapping['mapping'], search_paths) commands = mapping_data.get('commands', []) if not mapping_enabled: for command in commands: command['enabled'] = False all_commands.extend(commands) if mapping_enabled: all_initializers.extend(mapping_data.get('initializers', [])) all_loopers.extend(mapping_data.get('loopers', [])) all_extra_sources.update( set(mapping_data.get('extra_sources', set()))) messages = mapping_data.get('messages', []) if len(messages) == 0: LOG.warning("Mapping file '%s' doesn't define any messages" % mapping['mapping']) if 'database' in mapping: messages = merge(merge_database_into_mapping( find_file(mapping['database'], search_paths), messages)['messages'], messages) for message_id, message in messages.items(): message['id'] = message_id message.setdefault('bus', bus_name) message.setdefault('enabled', mapping_enabled) all_messages.extend(messages.values()) return {'messages': all_messages, 'commands': all_commands, 'initializers': all_initializers, 'extra_sources': all_extra_sources, 'loopers': all_loopers}