Example #1
0
 def test_set_nonunique_values(self, quiet_logger, yamlpath, value, verifications):
     yamldata = """---
     aliases:
       - &alias_number 1
       - &alias_bool true
     number: 1
     bool: true
     alias_number: *alias_number
     alias_bool: *alias_bool
     hash:
       number: 1
       bool: true
       alias_number: *alias_number
       alias_bool: *alias_bool
     complex:
       hash:
         number: 1
         bool: true
         alias_number: *alias_number
         alias_bool: *alias_bool
     """
     yaml = YAML()
     data = yaml.load(yamldata)
     processor = Processor(quiet_logger, data)
     processor.set_value(yamlpath, value)
     for verification in verifications:
         for verify_node_coord in processor.get_nodes(verification[0]):
             assert unwrap_node_coords(verify_node_coord) == verification[1]
Example #2
0
    def test_key_anchor_changes(self, quiet_logger, yamlpath, value, tally, mustexist, vformat, pathsep):
        yamldata = """---
        anchorKeys:
          &keyOne aliasOne: 11A1
          &keyTwo aliasTwo: 22B2
          &recursiveAnchorKey subjectKey: *recursiveAnchorKey

        hash:
          *keyOne :
            subval: 1.1
          *keyTwo :
            subval: 2.2
          *recursiveAnchorKey :
            subval: 3.3
        """
        yaml = YAML()
        data = yaml.load(yamldata)
        processor = Processor(quiet_logger, data)

        yamlpath = YAMLPath(yamlpath)
        processor.set_value(yamlpath, value, mustexist=mustexist, value_format=vformat, pathsep=pathsep)
        matchtally = 0
        for node in processor.get_nodes(yamlpath):
            assert unwrap_node_coords(node) == value
            matchtally += 1
        assert matchtally == tally
Example #3
0
    def test_set_value(self, quiet_logger, yamlpath, value, tally, mustexist, vformat, pathsep):
        yamldata = """---
aliases:
  - &testAnchor Initial Value
top_array:
  # Comment 1
  - 1
  # Comment 2
  - 2
# Comment N
top_scalar: Top-level plain scalar string
top_hash:
  positive_float: 3.14159265358
  negative_float: -11.034
null_value:
        """
        yaml = YAML()
        data = yaml.load(yamldata)
        processor = Processor(quiet_logger, data)
        processor.set_value(yamlpath, value, mustexist=mustexist, value_format=vformat, pathsep=pathsep)
        matchtally = 0
        for node in processor.get_nodes(yamlpath, mustexist=mustexist):
            assert unwrap_node_coords(node) == value
            matchtally += 1
        assert matchtally == tally
Example #4
0
 def test_set_value(self, quiet_logger, yamlpath, value, tally, mustexist,
                    vformat, pathsep):
     yamldata = """---
     aliases:
       - &testAnchor Initial Value
     top_array:
       # Comment 1
       - 1
       # Comment 2
       - 2
     # Comment N
     top_scalar: Top-level plain scalar string
     """
     yaml = YAML()
     data = yaml.load(yamldata)
     processor = Processor(quiet_logger, data)
     processor.set_value(yamlpath,
                         value,
                         mustexist=mustexist,
                         value_format=vformat,
                         pathsep=pathsep)
     matchtally = 0
     for node in processor.get_nodes(yamlpath, mustexist=mustexist):
         assert node == value
         matchtally += 1
     assert matchtally == tally
Example #5
0
 def test_set_value_in_empty_data(self, capsys, quiet_logger):
     import sys
     yamldata = ""
     yaml = YAML()
     data = yaml.load(yamldata)
     processor = Processor(quiet_logger, data)
     processor.set_value("abc", "void")
     yaml.dump(data, sys.stdout)
     assert -1 == capsys.readouterr().out.find("abc")
Example #6
0
    def test_cannot_set_nonexistent_required_node_error(self, quiet_logger):
        yamldata = """---
        key: value
        """
        yaml = YAML()
        data = yaml.load(yamldata)
        processor = Processor(quiet_logger, data)

        with pytest.raises(YAMLPathException) as ex:
            processor.set_value("abc", "void", mustexist=True)
        assert -1 < str(ex.value).find("No nodes matched")
Example #7
0
    def test_non_int_slice_error(self, quiet_logger):
        yamldata = """---
        - step: 1
        - step: 2
        - step: 3
        """
        yaml = YAML()
        data = yaml.load(yamldata)
        processor = Processor(quiet_logger, data)

        with pytest.raises(YAMLPathException) as ex:
            processor.set_value("[1:4F]", "")
        assert -1 < str(ex.value).find("is not an integer array slice")
Example #8
0
    def test_key_anchor_children(self, quiet_logger):
        yamldata = """---
        anchorKeys:
          &keyOne aliasOne: 1 1 Alpha 1
          &keyTwo aliasTwo: 2 2 Beta 2

        hash:
          *keyOne :
            subval: 1.1
          *keyTwo :
            subval: 2.2
        """
        yaml = YAML()
        data = yaml.load(yamldata)
        processor = Processor(quiet_logger, data)

        yamlpath = YAMLPath("hash[&keyTwo].subval")
        newvalue = "Mute audibles"
        processor.set_value(yamlpath, newvalue, mustexist=True)
        matchtally = 0
        for node in processor.get_nodes(yamlpath):
            assert unwrap_node_coords(node) == newvalue
            matchtally += 1
        assert matchtally == 1
Example #9
0
 def _insert_scalar(
     self, insert_at: YAMLPath, lhs: Any, lhs_proc: Processor, rhs: Any
 ) -> bool:
     """Insert an RHS scalar into the LHS document."""
     merge_performed = False
     if isinstance(lhs, CommentedSeq):
         self.logger.debug(
             "Merger::_insert_scalar:  Merging a scalar into a list.")
         Nodes.append_list_element(lhs, rhs)
         merge_performed = True
     elif isinstance(lhs, CommentedSet):
         self.logger.debug(
             "Merger::_insert_scalar:  Merging a scalar into a set.")
         self._merge_sets(
             lhs, CommentedSet([rhs]), insert_at,
             NodeCoords(rhs, None, None))
         merge_performed = True
     elif isinstance(lhs, CommentedMap):
         ex_message = (
             "Impossible to add Scalar value, {}, to a Hash without"
             " a key.  Change the value to a 'key: value' pair, a"
             " '{{key: value}}' Hash, or change the merge target to"
             " an Array or other Scalar value."
             ).format(rhs)
         if len(str(rhs)) < 1 and not sys.stdin.isatty():
             ex_message += (
                 "  You may be seeing this because your workflow"
                 " inadvertently opened a STDIN handle to {}.  If"
                 " this may be the case, try adding --nostdin or -S"
                 " so as to block unintentional STDIN reading."
             ).format(basename(sys.argv[0]))
         raise MergeException(ex_message, insert_at)
     else:
         lhs_proc.set_value(insert_at, rhs)
         merge_performed = True
     return merge_performed
Example #10
0
    def merge_with(self, rhs: Any) -> None:
        """
        Merge this document with another.

        Parameters:
        1. rhs (Any) The document to merge into this one.

        Returns:  N/A

        Raises:
        - `MergeException` when a clean merge is impossible.
        """
        # Do nothing when RHS is None (empty document)
        if rhs is None:
            return

        # Remove all comments (no sensible way to merge them)
        Parsers.delete_all_comments(rhs)

        # When LHS is None (empty document), just dump all of RHS into it,
        # honoring any --mergeat|-m location as best as possible.
        insert_at = self.config.get_insertion_point()
        if self.data is None:
            self.logger.debug("Replacing None data with:",
                              prefix="Merger::merge_with:  ",
                              data=rhs,
                              data_header="     *****")
            self.data = Nodes.build_next_node(insert_at, 0, rhs)
            self.logger.debug("Merged document is now:",
                              prefix="Merger::merge_with:  ",
                              data=self.data,
                              footer="     ***** ***** *****")
            if isinstance(rhs, (dict, list)):
                # Only Scalar values need further processing
                return

        # Resolve any anchor conflicts
        self._resolve_anchor_conflicts(rhs)

        # Prepare the merge rules
        self.config.prepare(rhs)

        # Identify a reasonable default should a DOM need to be built up to
        # receive the RHS data.
        default_val = rhs
        if isinstance(rhs, CommentedMap):
            default_val = {}
        elif isinstance(rhs, CommentedSeq):
            default_val = []

        # Loop through all insertion points and the elements in RHS
        merge_performed = False
        nodes: List[NodeCoords] = []
        lhs_proc = Processor(self.logger, self.data)
        for node_coord in lhs_proc.get_nodes(insert_at,
                                             default_value=default_val):
            nodes.append(node_coord)

        for node_coord in nodes:
            target_node = (node_coord.node if isinstance(
                node_coord.node,
                (CommentedMap, CommentedSeq)) else node_coord.parent)

            Parsers.set_flow_style(rhs,
                                   (target_node.fa.flow_style() if hasattr(
                                       target_node, "fa") else None))

            if isinstance(rhs, CommentedMap):
                # The RHS document root is a map
                if isinstance(target_node, CommentedSeq):
                    # But the destination is a list
                    self._merge_lists(target_node, CommentedSeq([rhs]),
                                      insert_at)
                else:
                    self._merge_dicts(target_node, rhs, insert_at)

                    # Synchronize YAML Tags
                    self.logger.debug(
                        "Merger::merge_with:  Setting LHS tag from {} to {}.".
                        format(target_node.tag.value, rhs.tag.value))
                    target_node.yaml_set_tag(rhs.tag.value)
                merge_performed = True
            elif isinstance(rhs, CommentedSeq):
                # The RHS document root is a list
                self._merge_lists(target_node, rhs, insert_at)
                merge_performed = True

                # Synchronize any YAML Tag
                self.logger.debug(
                    "Merger::merge_with:  Setting LHS tag from {} to {}.".
                    format(target_node.tag.value, rhs.tag.value))
                target_node.yaml_set_tag(rhs.tag.value)
            else:
                # The RHS document root is a Scalar value
                target_node = node_coord.node
                if isinstance(target_node, CommentedSeq):
                    Nodes.append_list_element(target_node, rhs)
                    merge_performed = True
                elif isinstance(target_node, CommentedMap):
                    raise MergeException(
                        "Impossible to add Scalar value, {}, to a Hash without"
                        " a key.  Change the value to a 'key: value' pair, a"
                        " '{{key: value}}' Hash, or change the merge target to"
                        " an Array or other Scalar value.".format(rhs),
                        insert_at)
                else:
                    lhs_proc.set_value(insert_at, rhs)
                    merge_performed = True

        self.logger.debug("Completed merge operation, resulting in document:",
                          prefix="Merger::merge_with:  ",
                          data=self.data)

        if not merge_performed:
            raise MergeException(
                "A merge was not performed.  Ensure your target path matches"
                " at least one node in the left document(s).", insert_at)