def yaml_seq_node(): # A yaml.SequenceNode representing a sequence of mappings tag1 = 'tag:yaml.org,2002:map' item1_key1_node = yaml.ScalarNode('tag:yaml.org,2002:str', 'item_id') item1_value1_node = yaml.ScalarNode('tag:yaml.org,2002:str', 'item1') item1_key2_node = yaml.ScalarNode('tag:yaml.org,2002:str', 'price') item1_value2_node = yaml.ScalarNode('tag:yaml.org,2002:float', '100.0') value1 = [(item1_key1_node, item1_value1_node), (item1_key2_node, item1_value2_node)] item1 = yaml.MappingNode(tag1, value1) tag2 = 'tag:yaml.org,2002:map' item2_key1_node = yaml.ScalarNode('tag:yaml.org,2002:str', 'item_id') item2_value1_node = yaml.ScalarNode('tag:yaml.org,2002:str', 'item2') item2_key2_node = yaml.ScalarNode('tag:yaml.org,2002:str', 'price') item2_value2_node = yaml.ScalarNode('tag:yaml.org,2002:float', '200.0') item2_key3_node = yaml.ScalarNode('tag:yaml.org,2002:str', 'on_sale') item2_value3_node = yaml.ScalarNode('tag:yaml.org,2002:bool', 'True') value2 = [(item2_key1_node, item2_value1_node), (item2_key2_node, item2_value2_node), (item2_key3_node, item2_value3_node)] item2 = yaml.MappingNode(tag2, value2) return yaml.SequenceNode('tag:yaml.org,2002:seq', [item1, item2])
def get_args_kwargs(cls, loader: yaml.Loader, node: yaml.Node, signature: Signature = free_signature) -> tp.Optional[BoundArguments]: if isinstance(node, yaml.ScalarNode): try: # This sometimes fails because of ruamel/yaml/resolver.py line 370 node.tag = loader.resolver.resolve(yaml.ScalarNode, node.value, [True, False]) except IndexError: node.tag = loader.DEFAULT_SCALAR_TAG val = loader.construct_object(node) if val is None: val = loader.yaml_constructors[node.tag](loader, node) return None if val is None else signature.bind(val) elif isinstance(node, yaml.SequenceNode): bound = signature.bind(*node.value) args = [] subnodes = node.value elif isinstance(node, yaml.MappingNode): # Construct the keys kwargs = {loader.construct_object(key, deep=True): val for key, val in node.value} args = kwargs.setdefault('__args', yaml.SequenceNode('tag:yaml.org,2002:seq', [])) args_is_seq = isinstance(args, yaml.SequenceNode) and args.tag == 'tag:yaml.org,2002:seq' if args_is_seq: kwargs['__args'] = args.value # Extract nodes in order (nodes are not iterable, so only "flattens" __args) subnodes = list(flatten(kwargs.values())) __args = kwargs.pop('__args') bound = signature.bind_partial(*(__args if args_is_seq else ()), **kwargs) else: raise ValueError(f'Invalid node type, {node}') # Experimental cls.fix_signature(bound) # Construct nodes in yaml order subnode_values = {n: loader.construct_object(n, deep=True) for n in subnodes} for key, val in bound.arguments.items(): bound.arguments[key] = ( signature.parameters[key].kind == Parameter.VAR_POSITIONAL and (subnode_values[n] for n in val) or signature.parameters[key].kind == Parameter.VAR_KEYWORD and {name: subnode_values[n] for name, n in val.items()} or subnode_values[val] ) if args and args in subnode_values: return bound.signature.bind(*subnode_values[args], **bound.kwargs) return bound
def yatiml_savorize(cls, node: yatiml.Node) -> None: text = str(node.get_value()) parts = text.split('.') node.make_mapping() # We need to make a yaml.SequenceNode by hand here, since # set_attribute doesn't take lists as an argument. start_mark = yaml.error.StreamMark('generated node', 0, 0, 0) end_mark = yaml.error.StreamMark('generated node', 0, 0, 0) item_nodes = list() for part in parts[:-1]: item_nodes.append( yaml.ScalarNode('tag:yaml.org,2002:str', part, start_mark, end_mark)) ynode = yaml.SequenceNode('tag:yaml.org,2002:seq', item_nodes, start_mark, end_mark) node.set_attribute('namespaces', ynode) node.set_attribute('name', parts[-1])
def _yatiml_sweeten(cls, node: yatiml.Node) -> None: script_node = node.get_attribute('script') if script_node.is_scalar(str): text = cast(str, script_node.get_value()) if '\n' in text: # make a sequence of lines lines = text.split('\n') start_mark = node.yaml_node.start_mark end_mark = node.yaml_node.end_mark lines_nodes = [ yaml.ScalarNode( 'tag:yaml.org,2002:str', line, start_mark, end_mark) for line in lines] seq_node = yaml.SequenceNode( 'tag:yaml.org,2002:seq', lines_nodes, start_mark, end_mark) node.set_attribute('script', seq_node)
def class_node_dup_key(): # A Node wrapping a yaml.SequenceNode representing a sequence of # mappings with a duplicate key. tag1 = 'tag:yaml.org,2002:map' item1_key1_node = yaml.ScalarNode('tag:yaml.org,2002:str', 'item_id') item1_value1_node = yaml.ScalarNode('tag:yaml.org,2002:str', 'item') value1 = [(item1_key1_node, item1_value1_node)] item1 = yaml.MappingNode(tag1, value1) tag2 = 'tag:yaml.org,2002:map' item2_key1_node = yaml.ScalarNode('tag:yaml.org,2002:str', 'item_id') item2_value1_node = yaml.ScalarNode('tag:yaml.org,2002:str', 'item') value2 = [(item2_key1_node, item2_value1_node)] item2 = yaml.MappingNode(tag2, value2) seq_node = yaml.SequenceNode('tag:yaml.org,2002:seq', [item1, item2]) list1_key_node = yaml.ScalarNode('tag:yaml.org,2002:str', 'dup_list') value = [(list1_key_node, seq_node)] map_node = yaml.MappingNode('tag:yaml.org,2002:map', value) return yatiml.Node(map_node)
def map_attribute_to_seq(self, attribute: str, key_attribute: str, value_attribute: Optional[str] = None) -> None: """Converts a mapping attribute to a sequence. This function takes an attribute of this Node whose value \ is a mapping or a mapping of mappings and turns it into a \ sequence of mappings. Each entry in the original mapping is \ converted to an entry in the list. If only a key attribute is \ given, then each entry in the original mapping must map to a \ (sub)mapping. This submapping becomes the corresponding list \ entry, with the key added to it as an additional attribute. If a \ value attribute is also given, then an entry in the original \ mapping may map to any object. If the mapped-to object is a \ mapping, the conversion is as before, otherwise a new \ submapping is created, and key and value are added using the \ given key and value attribute names. An example probably helps. If you have a Node representing \ this piece of YAML:: items: item1: description: Basic widget price: 100.0 item2: description: Premium quality widget price: 200.0 and call map_attribute_to_seq('items', 'item_id'), then the \ Node will be modified to represent this:: items: - item_id: item1 description: Basic widget price: 100.0 - item_id: item2 description: Premium quality widget price: 200.0 which once converted to an object is often easier to deal with \ in code. Slightly more complicated, this YAML:: items: item1: Basic widget item2: description: Premium quality widget price: 200.0 when passed through map_attribute_to_seq('items', 'item_id', \ 'description'), will result in th equivalent of:: items: - item_id: item1 description: Basic widget - item_id: item2 description: Premium quality widget price: 200.0 If the attribute does not exist, or is not a mapping, this \ function will silently do nothing. With thanks to the makers of the Common Workflow Language for \ the idea. Args: attribute: Name of the attribute whose value to modify. key_attribute: Name of the new attribute in each item to \ add with the value of the key. value_attribute: Name of the new attribute in each item to \ add with the value of the key. """ if not self.has_attribute(attribute): return attr_node = self.get_attribute(attribute) if not attr_node.is_mapping(): return start_mark = attr_node.yaml_node.start_mark end_mark = attr_node.yaml_node.end_mark object_list = [] for item_key, item_value in attr_node.yaml_node.value: item_value_node = Node(item_value) if not item_value_node.is_mapping(): if value_attribute is None: return ynode = item_value_node.yaml_node item_value_node.make_mapping() item_value_node.set_attribute(value_attribute, ynode) item_value_node.set_attribute(key_attribute, item_key.value) object_list.append(item_value_node.yaml_node) seq_node = yaml.SequenceNode('tag:yaml.org,2002:seq', object_list, start_mark, end_mark) self.set_attribute(attribute, seq_node)
def unknown_sequence_node(): ynode = yaml.SequenceNode('tag:yaml.org,2002:seq', []) return yatiml.UnknownNode(Recognizer({}), ynode)
def unknown_sequence_node(recognizer: Recognizer) -> yatiml.UnknownNode: ynode = yaml.SequenceNode('tag:yaml.org,2002:seq', []) return yatiml.UnknownNode(recognizer, ynode)