openrvdas.logger.utils.formats

#

DEPRECATED! Please see logger/utils/base_module.py for the now-preferred way to validate component inputs.

#

Set of hierarchical utility classes used to check for input/output compatibility between Readers, Writers and Transforms.

The idea is that each class defined here (or elsewhere) represents a particular data exchange format, including everything from raw binary (Bytes) to JSON encodings of RVDAS Records (JSON_Record). Processes that accept inputs higher in the inheritance tree can also accept inputs that inherit from them. So something that accepts Text can also accept NMEA or XML, but not vice versa.

The only methods defined here are class methods belonging to the base class (Bytes):

A.can_accept(B) - true iff format A can accept format B, e.g. assertTrue(JSON.can_accept(JSON_Record))

A.common(B) - the lowest common format A and B share, e.g. XML.common(JSON_Record) == Text

Reader objects are intended to be instantiated such that their output_format() method returns a format class, and Writers such that their input_format() method also returns one. It is the responsibility of whatever program look encloses them to ensure compatibility by checking that

writer.input_format().can_accept(reader.output_format())

Transforms have both an input_format() and output_format(), with the unsolved complication that, for some transforms, the output format depends on the input format.

Currently-defined format hierarchy is:

Bytes
  Text
    NMEA
    JSON - generic JSON string
      JSON_Record - JSON string representing a DAS Record
    XML
      XML_OSU
  Python - e.g. a dict or list
    Python_Record - a Python DAS Record

There is also a special case 'Unknown' format that can't accept anything, and has no common elements with any other format.

  1#!/usr/bin/env python3
  2
  3"""
  4###############################################################################
  5DEPRECATED!  Please see logger/utils/base_module.py for the now-preferred way to
  6validate component inputs.
  7###############################################################################
  8
  9Set of hierarchical utility classes used to check for input/output
 10compatibility between Readers, Writers and Transforms.
 11
 12The idea is that each class defined here (or elsewhere) represents a
 13particular data exchange format, including everything from raw binary
 14(Bytes) to JSON encodings of RVDAS Records (JSON_Record). Processes
 15that accept inputs higher in the inheritance tree can also accept
 16inputs that inherit from them. So something that accepts Text can also
 17accept NMEA or XML, but not vice versa.
 18
 19The only methods defined here are class methods belonging to the base
 20class (Bytes):
 21
 22  A.can_accept(B) - true iff format A can accept format B, e.g.
 23     assertTrue(JSON.can_accept(JSON_Record))
 24
 25  A.common(B) - the lowest common format A and B share, e.g.
 26     XML.common(JSON_Record) == Text
 27
 28Reader objects are intended to be instantiated such that their
 29output_format() method returns a format class, and Writers such that
 30their input_format() method also returns one. It is the responsibility
 31of whatever program look encloses them to ensure compatibility by
 32checking that
 33
 34  writer.input_format().can_accept(reader.output_format())
 35
 36Transforms have both an input_format() and output_format(), with the
 37unsolved complication that, for some transforms, the output format
 38depends on the input format.
 39
 40Currently-defined format hierarchy is:
 41
 42    Bytes
 43      Text
 44        NMEA
 45        JSON - generic JSON string
 46          JSON_Record - JSON string representing a DAS Record
 47        XML
 48          XML_OSU
 49      Python - e.g. a dict or list
 50        Python_Record - a Python DAS Record
 51
 52There is also a special case 'Unknown' format that can't accept
 53anything, and has no common elements with any other format.
 54
 55"""
 56import logging
 57
 58logging.warning('Coding error: Module "formats" is deprecated. Please use type hints, as '
 59                'described in logging/utils/base_module.py.')
 60
 61
 62########################################
 63# Test whether the passed object is actually a valid format, as
 64# defined in this file.
 65def is_format(format):
 66    # Is format even a class?
 67    if not isinstance(format, type(Bytes)):
 68        return False
 69
 70    # Is it a class that inherits from one of the format classes defined here?
 71    if format == Unknown or Bytes.can_accept(format):
 72        return True
 73
 74    return False
 75
 76
 77########################################
 78# 'Unknown' is a special case format - it can't accept anything, and
 79# has no other common formats
 80class Unknown:
 81    @classmethod
 82    def can_accept(self, other_format):
 83        return False
 84
 85    @classmethod
 86    def common(self, other_format):
 87        return None
 88
 89
 90########################################
 91# 'Bytes' is the highest, most general format in the hierarchy. All
 92# more-specific formats inherit from it.
 93class Bytes:
 94    @classmethod
 95    def can_accept(self, other_format):
 96        return self in other_format.mro()
 97
 98    # Most specific common format
 99    @classmethod
100    def common(self, other_format):
101        # We have nothing in common with Unknown
102        if not other_format or other_format == Unknown:
103            return None
104
105        # Chase up module resolution order of superclasses for a match
106        other_hierarchy = other_format.mro()
107        for c in self.mro():
108            if c in other_hierarchy:
109                return c
110        # Shouldn't actually get here, but...
111        return None
112
113
114class Text(Bytes):
115    pass
116
117
118class NMEA(Text):
119    pass
120
121
122class JSON(Text):
123    pass
124
125
126class JSON_Record(JSON):
127    pass
128
129
130class Python(Bytes):
131    pass
132
133
134class Python_Record(Python):
135    pass
136
137
138class XML(Text):
139    pass
140
141
142class XML_OSU(XML):
143    pass
def is_format(format):
66def is_format(format):
67    # Is format even a class?
68    if not isinstance(format, type(Bytes)):
69        return False
70
71    # Is it a class that inherits from one of the format classes defined here?
72    if format == Unknown or Bytes.can_accept(format):
73        return True
74
75    return False
class Unknown:
81class Unknown:
82    @classmethod
83    def can_accept(self, other_format):
84        return False
85
86    @classmethod
87    def common(self, other_format):
88        return None
@classmethod
def can_accept(self, other_format):
82    @classmethod
83    def can_accept(self, other_format):
84        return False
@classmethod
def common(self, other_format):
86    @classmethod
87    def common(self, other_format):
88        return None
class Bytes:
 94class Bytes:
 95    @classmethod
 96    def can_accept(self, other_format):
 97        return self in other_format.mro()
 98
 99    # Most specific common format
100    @classmethod
101    def common(self, other_format):
102        # We have nothing in common with Unknown
103        if not other_format or other_format == Unknown:
104            return None
105
106        # Chase up module resolution order of superclasses for a match
107        other_hierarchy = other_format.mro()
108        for c in self.mro():
109            if c in other_hierarchy:
110                return c
111        # Shouldn't actually get here, but...
112        return None
@classmethod
def can_accept(self, other_format):
95    @classmethod
96    def can_accept(self, other_format):
97        return self in other_format.mro()
@classmethod
def common(self, other_format):
100    @classmethod
101    def common(self, other_format):
102        # We have nothing in common with Unknown
103        if not other_format or other_format == Unknown:
104            return None
105
106        # Chase up module resolution order of superclasses for a match
107        other_hierarchy = other_format.mro()
108        for c in self.mro():
109            if c in other_hierarchy:
110                return c
111        # Shouldn't actually get here, but...
112        return None
class Text(Bytes):
115class Text(Bytes):
116    pass
Inherited Members
Bytes
can_accept
common
class NMEA(Text):
119class NMEA(Text):
120    pass
Inherited Members
Bytes
can_accept
common
class JSON(Text):
123class JSON(Text):
124    pass
Inherited Members
Bytes
can_accept
common
class JSON_Record(JSON):
127class JSON_Record(JSON):
128    pass
Inherited Members
Bytes
can_accept
common
class Python(Bytes):
131class Python(Bytes):
132    pass
Inherited Members
Bytes
can_accept
common
class Python_Record(Python):
135class Python_Record(Python):
136    pass
Inherited Members
Bytes
can_accept
common
class XML(Text):
139class XML(Text):
140    pass
Inherited Members
Bytes
can_accept
common
class XML_OSU(XML):
143class XML_OSU(XML):
144    pass
Inherited Members
Bytes
can_accept
common