def multi_constructor(loader, tag_suffix, node): """ Deal with !Ref style function format """ if tag_suffix not in UNCONVERTED_SUFFIXES: tag_suffix = '{}{}'.format(FN_PREFIX, tag_suffix) constructor = None if tag_suffix == 'Fn::GetAtt': constructor = construct_getatt elif isinstance(node, ScalarNode): constructor = loader.construct_scalar elif isinstance(node, SequenceNode): constructor = loader.construct_sequence elif isinstance(node, MappingNode): constructor = loader.construct_mapping else: raise 'Bad tag: !{}'.format(tag_suffix) if tag_suffix == 'Fn::Sub': return sub_node({tag_suffix: constructor(node)}, node.start_mark, node.end_mark) return dict_node({tag_suffix: constructor(node)}, node.start_mark, node.end_mark)
def construct_yaml_map(self, node): # Check for duplicate keys on the current level, this is not desirable # because a dict does not support this. It overwrites it with the last # occurance, which can give unexpected results mapping = {} self.flatten_mapping(node) for key_node, value_node in node.value: key = self.construct_object(key_node, False) value = self.construct_object(value_node, False) for key_dup in mapping: if key_dup == key: raise CfnParseError(self.filename, [ build_match( filename=self.filename, message='Duplicate resource found "{}" (line {})'. format(key, key_dup.start_mark.line + 1), line_number=key_dup.start_mark.line, column_number=key_dup.start_mark.column, key=key), build_match( filename=self.filename, message='Duplicate resource found "{}" (line {})'. format(key, key_node.start_mark.line + 1), line_number=key_node.start_mark.line, column_number=key_node.start_mark.column, key=key), ]) try: mapping[key] = value except: raise CfnParseError(self.filename, [ build_match( filename=self.filename, message= f'Unhashable type "{key}" (line {key.start_mark.line + 1})', line_number=key.start_mark.line, column_number=key.start_mark.column, key=key), ]) obj, = SafeConstructor.construct_yaml_map(self, node) if len(mapping) == 1: if 'Fn::Sub' in mapping: return sub_node(obj, node.start_mark, node.end_mark) return dict_node(obj, node.start_mark, node.end_mark)
def check_duplicates(ordered_pairs, beg_mark, end_mark): """ Check for duplicate keys on the current level, this is not desirable because a dict does not support this. It overwrites it with the last occurrence, which can give unexpected results """ mapping = dict_node({}, beg_mark, end_mark) for key, value in ordered_pairs: if value is None: raise NullError('"{}"'.format(key)) if key in mapping: raise DuplicateError('"{}"'.format(key), mapping, key) mapping[key] = value if len(mapping) == 1: if 'Fn::Sub' in mapping: return sub_node(ordered_pairs, beg_mark, end_mark) return mapping