Ejemplo n.º 1
0
def main():
    """Main code."""
    args = processcli()
    log = ConsolePrinter(args)
    validateargs(args, log)
    yaml_path = YAMLPath(args.query, pathsep=args.pathsep)

    # Prep the YAML parser
    yaml = Parsers.get_yaml_editor()

    # Attempt to open the YAML file; check for parsing errors
    (yaml_data, doc_loaded) = Parsers.get_yaml_data(
        yaml, log, args.yaml_file if args.yaml_file else "-")
    if not doc_loaded:
        # An error message has already been logged
        sys.exit(1)

    # Seek the queried value(s)
    discovered_nodes = []
    processor = EYAMLProcessor(log,
                               yaml_data,
                               binary=args.eyaml,
                               publickey=args.publickey,
                               privatekey=args.privatekey)
    try:
        for node in processor.get_eyaml_values(yaml_path, mustexist=True):
            log.debug("Got node from {}:".format(yaml_path),
                      data=node,
                      prefix="yaml_get::main:  ")
            discovered_nodes.append(NodeCoords.unwrap_node_coords(node))
    except YAMLPathException as ex:
        log.critical(ex, 1)
    except EYAMLCommandException as ex:
        log.critical(ex, 2)

    try:
        for node in discovered_nodes:
            if isinstance(node, (dict, list, CommentedSet)):
                print(json.dumps(Parsers.jsonify_yaml_data(node)))
            else:
                if node is None:
                    node = "\x00"
                print("{}".format(str(node).replace("\n", r"\n")))
    except RecursionError:
        log.critical(
            "The YAML data contains an infinitely recursing YAML Alias!", 1)
Ejemplo n.º 2
0
    def min(data: Any, invert: bool, parameters: List[str],
            yaml_path: YAMLPath,
            **kwargs: Any) -> Generator[NodeCoords, None, None]:
        """
        Find whichever nodes/elements have a minimum value.

        Parameters:
        1. data (Any) The data to evaluate
        2. invert (bool) Invert the evaluation
        3. parameters (List[str]) Parsed parameters
        4. yaml_path (YAMLPath) YAML Path begetting this operation

        Keyword Arguments:
        * parent (ruamel.yaml node) The parent node from which this query
          originates
        * parentref (Any) The Index or Key of data within parent
        * relay_segment (PathSegment) YAML Path segment presently under
          evaluation
        * translated_path (YAMLPath) YAML Path indicating precisely which node
          is being evaluated
        * ancestry (List[AncestryEntry]) Stack of ancestors preceding the
          present node under evaluation

        Returns:  (Generator[NodeCoords, None, None]) each result as it is
            generated
        """
        parent: Any = kwargs.pop("parent", None)
        parentref: Any = kwargs.pop("parentref", None)
        translated_path: YAMLPath = kwargs.pop("translated_path", YAMLPath(""))
        ancestry: List[AncestryEntry] = kwargs.pop("ancestry", [])
        relay_segment: PathSegment = kwargs.pop("relay_segment", None)

        # There may be 0 or 1 parameters
        param_count = len(parameters)
        if param_count > 1:
            raise YAMLPathException(
                ("Invalid parameter count to {}([NAME]); up to {} permitted, "
                 " got {} in YAML Path").format(PathSearchKeywords.MIN, 1,
                                                param_count), str(yaml_path))

        scan_node = parameters[0] if param_count > 0 else None
        match_value: Any = None
        match_nodes: List[NodeCoords] = []
        discard_nodes: List[NodeCoords] = []
        unwrapped_data: Any = NodeCoords.unwrap_node_coords(data)
        if Nodes.node_is_aoh(unwrapped_data, accept_nulls=True):
            # A named child node is mandatory
            if scan_node is None:
                raise YAMLPathException((
                    "The {}([NAME]) Search Keyword requires a key name to scan"
                    " when evaluating an Array-of-Hashes in YAML Path").format(
                        PathSearchKeywords.MIN), str(yaml_path))

            for idx, wrapped_ele in enumerate(data):
                ele = NodeCoords.unwrap_node_coords(wrapped_ele)
                next_path = translated_path + "[{}]".format(idx)
                next_ancestry = ancestry + [(data, idx)]
                if ele is not None and scan_node in ele:
                    eval_val = ele[scan_node]
                    if (match_value is None or Searches.search_matches(
                            PathSearchMethods.LESS_THAN, match_value,
                            eval_val)):
                        match_value = eval_val
                        discard_nodes.extend(match_nodes)
                        match_nodes = [
                            NodeCoords(ele, data, idx, next_path,
                                       next_ancestry, relay_segment)
                        ]
                        continue

                    if (match_value is None or Searches.search_matches(
                            PathSearchMethods.EQUALS, match_value, eval_val)):
                        match_nodes.append(
                            NodeCoords(ele, data, idx, next_path,
                                       next_ancestry, relay_segment))
                        continue

                discard_nodes.append(
                    NodeCoords(ele, data, idx, next_path, next_ancestry,
                               relay_segment))

        elif isinstance(data, dict):
            # A named child node is mandatory
            if scan_node is None:
                raise YAMLPathException((
                    "The {}([NAME]) Search Keyword requires a key name to scan"
                    " when comparing Hash/map/dict children in YAML Path"
                ).format(PathSearchKeywords.MIN), str(yaml_path))

            for key, val in data.items():
                next_ancestry = ancestry + [(data, key)]
                next_path = (translated_path + YAMLPath.escape_path_section(
                    key, translated_path.seperator))
                if isinstance(val, dict):
                    if val is not None and scan_node in val:
                        eval_val = val[scan_node]
                        if (match_value is None or Searches.search_matches(
                                PathSearchMethods.LESS_THAN, match_value,
                                eval_val)):
                            match_value = eval_val
                            discard_nodes.extend(match_nodes)
                            match_nodes = [
                                NodeCoords(val, data, key, next_path,
                                           next_ancestry, relay_segment)
                            ]
                            continue

                        if (match_value is None or Searches.search_matches(
                                PathSearchMethods.EQUALS, match_value,
                                eval_val)):
                            match_nodes.append(
                                NodeCoords(val, data, key, next_path,
                                           next_ancestry, relay_segment))
                            continue

                elif scan_node in data:
                    # The user probably meant to operate against the parent
                    raise YAMLPathException(
                        ("The {}([NAME]) Search Keyword operates against"
                         " collections of data which share a common attribute"
                         " yet there is only a single node to consider.  Did"
                         " you mean to evaluate the parent of the selected"
                         " node?  Please review your YAML Path").format(
                             PathSearchKeywords.MIN), str(yaml_path))

                discard_nodes.append(
                    NodeCoords(val, data, key, next_path, next_ancestry,
                               relay_segment))

        elif isinstance(data, list):
            # A named child node is useless
            if scan_node is not None:
                raise YAMLPathException(
                    ("The {}([NAME]) Search Keyword cannot utilize a key name"
                     " when comparing Array/sequence/list elements to one"
                     " another in YAML Path").format(PathSearchKeywords.MIN),
                    str(yaml_path))

            for idx, ele in enumerate(data):
                next_path = translated_path + "[{}]".format(idx)
                next_ancestry = ancestry + [(data, idx)]
                if (ele is not None
                        and (match_value is None or Searches.search_matches(
                            PathSearchMethods.LESS_THAN, match_value, ele))):
                    match_value = ele
                    discard_nodes.extend(match_nodes)
                    match_nodes = [
                        NodeCoords(ele, data, idx, next_path, next_ancestry,
                                   relay_segment)
                    ]
                    continue

                if (ele is not None and Searches.search_matches(
                        PathSearchMethods.EQUALS, match_value, ele)):
                    match_nodes.append(
                        NodeCoords(ele, data, idx, next_path, next_ancestry,
                                   relay_segment))
                    continue

                discard_nodes.append(
                    NodeCoords(ele, data, idx, next_path, next_ancestry,
                               relay_segment))

        else:
            # Non-complex data is always its own maximum and does not invert
            match_value = data
            match_nodes = [
                NodeCoords(data, parent, parentref, translated_path, ancestry,
                           relay_segment)
            ]

        yield_nodes = discard_nodes if invert else match_nodes
        for node_coord in yield_nodes:
            yield node_coord
Ejemplo n.º 3
0
def unwrap_node_coords(*args):
    """Relay function call to static method."""
    return NodeCoords.unwrap_node_coords(*args)