Example #1
0
    def count_aggs(self,
                   module: abc.Mapping,
                   obj_count: int = 0,
                   grp_count: int = 0) -> tuple((int, int)):
        """Returns the count of OBJECT and GROUP aggregations
        that are contained within the *module* as a two-tuple
        in that order.
        """
        # This currently just counts the values in the passed
        # in module, it does not 'recurse' if those aggregations also
        # may contain aggregations.

        for k, v in module.items():
            if isinstance(v, abc.Mapping):
                if isinstance(v, self.grpcls):
                    grp_count += 1
                elif isinstance(v, self.objcls):
                    obj_count += 1
                else:
                    # We treat other dict-like Python objects as
                    # PVL Objects for the purposes of this count,
                    # because that is how they will be encoded.
                    obj_count += 1

        return obj_count, grp_count
Example #2
0
    def serialize_mapping(self, obj: abc.Mapping):
        """
        Mappings are just copied into another mapping. While copying, all the
        values are recursively serialized.
        """

        return {k: self.serialize(v) for k, v in obj.items()}
Example #3
0
    def is_PDSgroup(self, group: abc.Mapping) -> bool:
        """Returns true if the dict-like *group* qualifies as a PDS Group,
        false otherwise.

        PDS applies the following restrictions to GROUPS:

        1. The GROUP structure may only be used in a data product
           label which also contains one or more data OBJECT definitions.
        2. The GROUP statement must contain only attribute assignment
           statements, include pointers, or related information pointers
           (i.e., no data location pointers). If there are multiple
           values, a single statement must be used with either sequence
           or set syntax; no attribute assignment statement or pointer
           may be repeated.
        3. GROUP statements may not be nested.
        4. GROUP statements may not contain OBJECT definitions.
        5. Only PSDD elements may appear within a GROUP statement.
           *PSDD is not defined anywhere in the PDS document, so don't
           know how to test for it.*
        6. The keyword contents associated with a specific GROUP
           identifier must be identical across all labels of a single data
           set (with the exception of the “PARAMETERS” GROUP, as
           explained).

        Use of the GROUP structure must be coordinated with the
        responsible PDS discipline Node.

        Items 1 & 6 and the final sentence above, can't really be tested
        by examining a single group, but must be dealt with in a larger
        context.  The ODLEncoder.encode_module() handles #1, at least.
        You're on your own for the other two issues.

        Item 5: *PSDD* is not defined anywhere in the ODL PDS document,
        so don't know how to test for it.
        """
        (obj_count, grp_count) = self.count_aggs(group)

        # Items 3 and 4:
        if obj_count != 0 or grp_count != 0:
            return False

        # Item 2, no data location pointers:
        for k, v in group.items():
            if k.startswith("^"):
                if isinstance(v, int):
                    return False
                else:
                    for quant in self.quantities:
                        if isinstance(v, quant.cls) and isinstance(
                                getattr(v, quant.value_prop), int):
                            return False

        # Item 2, no repeated keys:
        keys = list(group.keys())
        if len(keys) != len(set(keys)):
            return False

        return True
Example #4
0
 def __init__(self, data: abc.Mapping):
     super(ReadOnlyDict, self).__init__()
     self._data = dict()
     for k, v in data.items():
         if isinstance(v, list):
             self._data.__setitem__(k, ReadOnlyList(v))
         elif isinstance(v, dict):
             self._data.__setitem__(k, ReadOnlyDict(v))
         else:
             self._data.__setitem__(k, v)
Example #5
0
    def encode_module(self, module: abc.Mapping, level: int = 0) -> str:
        """Returns a ``str`` formatted as a PVL module based
        on the dict-like *module* object according to the
        rules of this encoder, with an indentation level
        of *level*.
        """
        lines = list()

        # To align things on the equals sign, just need to normalize
        # the non-aggregation key length:

        non_agg_key_lengths = list()
        for k, v in module.items():
            if not isinstance(v, abc.Mapping):
                non_agg_key_lengths.append(len(k))
        longest_key_len = max(non_agg_key_lengths, default=0)

        for k, v in module.items():
            if isinstance(v, abc.Mapping):
                lines.append(self.encode_aggregation_block(k, v, level))
            else:
                lines.append(
                    self.encode_assignment(k, v, level, longest_key_len))
        return self.newline.join(lines)