openrvdas.logger.transforms.format_transform

Sample config file for using for FormatTransform. To run, copy the config below to a file, say 's330_format.yaml', then run

logger/listener/listen.py --config_file s330_format.yaml

Sample config:

# Read from stored logfile
readers:
  class: LogfileReader
  kwargs:
    filebase: test//NBP1406/s330/raw/NBP1406_s330-2014-08-01

# Logfile reader already has a timestamp, so we don't need to
# timestamp. Just add the instrument prefix and parse it.
transforms:
- class: PrefixTransform
  kwargs:
    prefix: s330
- class: ParseTransform
  kwargs:
    definition_path: local/usap/nbp/devices/nbp_devices.yaml

# Output a string showing course and speed. We only provide a default
# for course, so if course is missing, we will still output a string, but
# if speed is missing, we will output None instead of a string.
- class: FormatTransform
  module: logger.transforms.format_transform  # where the definition is
  kwargs:
    format_str: 'Course: {S330CourseTrue}, Speed: {S330SpeedKt}'
    defaults: {'S330CourseTrue': '-'}

# Output to stdout
writers:
- class: TextFileWriter
  1#!/usr/bin/env python3
  2"""
  3Sample config file for using for FormatTransform. To run, copy the config
  4below to a file, say 's330_format.yaml', then run
  5
  6  logger/listener/listen.py --config_file s330_format.yaml
  7
  8Sample config:
  9
 10    # Read from stored logfile
 11    readers:
 12      class: LogfileReader
 13      kwargs:
 14        filebase: test//NBP1406/s330/raw/NBP1406_s330-2014-08-01
 15
 16    # Logfile reader already has a timestamp, so we don't need to
 17    # timestamp. Just add the instrument prefix and parse it.
 18    transforms:
 19    - class: PrefixTransform
 20      kwargs:
 21        prefix: s330
 22    - class: ParseTransform
 23      kwargs:
 24        definition_path: local/usap/nbp/devices/nbp_devices.yaml
 25
 26    # Output a string showing course and speed. We only provide a default
 27    # for course, so if course is missing, we will still output a string, but
 28    # if speed is missing, we will output None instead of a string.
 29    - class: FormatTransform
 30      module: logger.transforms.format_transform  # where the definition is
 31      kwargs:
 32        format_str: 'Course: {S330CourseTrue}, Speed: {S330SpeedKt}'
 33        defaults: {'S330CourseTrue': '-'}
 34
 35    # Output to stdout
 36    writers:
 37    - class: TextFileWriter
 38"""
 39
 40from typing import Union
 41
 42from logger.utils.das_record import DASRecord  # noqa: E402
 43from logger.utils.timestamp import time_str  # noqa: E402
 44from logger.transforms.transform import Transform  # noqa: E402
 45
 46
 47################################################################################
 48class FormatTransform(Transform):
 49    def __init__(self, format_str, defaults=None, use_iso_timestamp=False, **kwargs):
 50        """
 51        Output a formatted string in which field values from a DASRecord or field
 52        dict have been substituted. An optional default_dict may be provided to
 53        indicate what value should be substituted in if the relevant record is
 54        missing any of the requested values.
 55
 56        format_str   - A format string, as described
 57                       https://www.w3schools.com/python/ref_string_format.asp
 58
 59                       E.g. format_str='Course: {S330CourseTrue}, Speed: {S330SpeedKt}kt',
 60                       would output 'Course: 227.3, Speed 7.3kt'
 61
 62
 63        default_dict - If omitted, transform will emit None if any of the fields
 64                       requested in the format string are missing.
 65
 66                       If not None, should be a dict of field:value pairs
 67                       specifying the value that should be substituted in
 68                       for any missing fields. If a field:value pair is missing
 69                       from this dict, return None for the relevant record.
 70
 71                       E.g. default_dict={'S330CourseTrue': '-'} would output
 72                       'Course: -, Speed 7.3kt' if S330CourseTrue were missing
 73                       from the input record, but would output None if S330SpeedKt
 74                       were missing (because no default was provided for
 75                       S330SpeedKt).
 76
 77        use_iso_timestamp - If True, ISO 8601 format timestamps when the {timestamp}
 78                       tag is present. Otherwise use Unix numerical timestamps.
 79        """
 80        super().__init__(**kwargs)  # processes 'quiet' and type hints
 81
 82        self.format_str = format_str
 83        self.defaults = defaults or {}
 84        self.use_uso_timestamp = use_iso_timestamp
 85
 86    def transform(self, record: Union[DASRecord, dict]) -> str:
 87        # See if it's something we can process, and if not, try digesting
 88        if not self.can_process_record(record):  # BaseModule
 89            return self.digest_record(record)  # BaseModule
 90
 91        if type(record) is DASRecord:
 92            record_fields = record.fields
 93        elif type(record) is dict:
 94            if 'fields' in record:
 95                record_fields = record['fields']
 96            else:
 97                record_fields = record
 98        else:
 99            return ('Record passed to FormatTransform was neither a dict nor a '
100                    'DASRecord. Type was %s: %s' % (type(record), str(record)[:80]))
101
102        fields = self.defaults.copy()
103
104        for field, value in record_fields.items():
105            fields[field] = value
106
107        # Add the timestamp as a field as well.
108        if type(record) is DASRecord:
109            fields['timestamp'] = record.timestamp
110        else:
111            fields['timestamp'] = record.get('timestamp', 0)
112
113        # If we're supposed to be outputting USO 8601 timestamps,
114        # convert to appropriate format
115        if self.use_uso_timestamp:
116            fields['timestamp'] = time_str(fields['timestamp'])
117
118        try:
119            result = self.format_str.format(**fields)
120
121        except KeyError:
122            result = None
123
124        if result:
125            return result
126        return None
class FormatTransform(logger.transforms.transform.Transform):
 49class FormatTransform(Transform):
 50    def __init__(self, format_str, defaults=None, use_iso_timestamp=False, **kwargs):
 51        """
 52        Output a formatted string in which field values from a DASRecord or field
 53        dict have been substituted. An optional default_dict may be provided to
 54        indicate what value should be substituted in if the relevant record is
 55        missing any of the requested values.
 56
 57        format_str   - A format string, as described
 58                       https://www.w3schools.com/python/ref_string_format.asp
 59
 60                       E.g. format_str='Course: {S330CourseTrue}, Speed: {S330SpeedKt}kt',
 61                       would output 'Course: 227.3, Speed 7.3kt'
 62
 63
 64        default_dict - If omitted, transform will emit None if any of the fields
 65                       requested in the format string are missing.
 66
 67                       If not None, should be a dict of field:value pairs
 68                       specifying the value that should be substituted in
 69                       for any missing fields. If a field:value pair is missing
 70                       from this dict, return None for the relevant record.
 71
 72                       E.g. default_dict={'S330CourseTrue': '-'} would output
 73                       'Course: -, Speed 7.3kt' if S330CourseTrue were missing
 74                       from the input record, but would output None if S330SpeedKt
 75                       were missing (because no default was provided for
 76                       S330SpeedKt).
 77
 78        use_iso_timestamp - If True, ISO 8601 format timestamps when the {timestamp}
 79                       tag is present. Otherwise use Unix numerical timestamps.
 80        """
 81        super().__init__(**kwargs)  # processes 'quiet' and type hints
 82
 83        self.format_str = format_str
 84        self.defaults = defaults or {}
 85        self.use_uso_timestamp = use_iso_timestamp
 86
 87    def transform(self, record: Union[DASRecord, dict]) -> str:
 88        # See if it's something we can process, and if not, try digesting
 89        if not self.can_process_record(record):  # BaseModule
 90            return self.digest_record(record)  # BaseModule
 91
 92        if type(record) is DASRecord:
 93            record_fields = record.fields
 94        elif type(record) is dict:
 95            if 'fields' in record:
 96                record_fields = record['fields']
 97            else:
 98                record_fields = record
 99        else:
100            return ('Record passed to FormatTransform was neither a dict nor a '
101                    'DASRecord. Type was %s: %s' % (type(record), str(record)[:80]))
102
103        fields = self.defaults.copy()
104
105        for field, value in record_fields.items():
106            fields[field] = value
107
108        # Add the timestamp as a field as well.
109        if type(record) is DASRecord:
110            fields['timestamp'] = record.timestamp
111        else:
112            fields['timestamp'] = record.get('timestamp', 0)
113
114        # If we're supposed to be outputting USO 8601 timestamps,
115        # convert to appropriate format
116        if self.use_uso_timestamp:
117            fields['timestamp'] = time_str(fields['timestamp'])
118
119        try:
120            result = self.format_str.format(**fields)
121
122        except KeyError:
123            result = None
124
125        if result:
126            return result
127        return None

Base class Transform about which we know nothing else.

Passes arguments quiet, encoding and encoding_errors up to BaseModule

FormatTransform(format_str, defaults=None, use_iso_timestamp=False, **kwargs)
50    def __init__(self, format_str, defaults=None, use_iso_timestamp=False, **kwargs):
51        """
52        Output a formatted string in which field values from a DASRecord or field
53        dict have been substituted. An optional default_dict may be provided to
54        indicate what value should be substituted in if the relevant record is
55        missing any of the requested values.
56
57        format_str   - A format string, as described
58                       https://www.w3schools.com/python/ref_string_format.asp
59
60                       E.g. format_str='Course: {S330CourseTrue}, Speed: {S330SpeedKt}kt',
61                       would output 'Course: 227.3, Speed 7.3kt'
62
63
64        default_dict - If omitted, transform will emit None if any of the fields
65                       requested in the format string are missing.
66
67                       If not None, should be a dict of field:value pairs
68                       specifying the value that should be substituted in
69                       for any missing fields. If a field:value pair is missing
70                       from this dict, return None for the relevant record.
71
72                       E.g. default_dict={'S330CourseTrue': '-'} would output
73                       'Course: -, Speed 7.3kt' if S330CourseTrue were missing
74                       from the input record, but would output None if S330SpeedKt
75                       were missing (because no default was provided for
76                       S330SpeedKt).
77
78        use_iso_timestamp - If True, ISO 8601 format timestamps when the {timestamp}
79                       tag is present. Otherwise use Unix numerical timestamps.
80        """
81        super().__init__(**kwargs)  # processes 'quiet' and type hints
82
83        self.format_str = format_str
84        self.defaults = defaults or {}
85        self.use_uso_timestamp = use_iso_timestamp

Output a formatted string in which field values from a DASRecord or field dict have been substituted. An optional default_dict may be provided to indicate what value should be substituted in if the relevant record is missing any of the requested values.

format_str - A format string, as described https://www.w3schools.com/python/ref_string_format.asp

           E.g. format_str='Course: {S330CourseTrue}, Speed: {S330SpeedKt}kt',
           would output 'Course: 227.3, Speed 7.3kt'

default_dict - If omitted, transform will emit None if any of the fields requested in the format string are missing.

           If not None, should be a dict of field:value pairs
           specifying the value that should be substituted in
           for any missing fields. If a field:value pair is missing
           from this dict, return None for the relevant record.

           E.g. default_dict={'S330CourseTrue': '-'} would output
           'Course: -, Speed 7.3kt' if S330CourseTrue were missing
           from the input record, but would output None if S330SpeedKt
           were missing (because no default was provided for
           S330SpeedKt).

use_iso_timestamp - If True, ISO 8601 format timestamps when the {timestamp} tag is present. Otherwise use Unix numerical timestamps.

format_str
defaults
use_uso_timestamp
def transform(self, record: Union[logger.utils.das_record.DASRecord, dict]) -> str:
 87    def transform(self, record: Union[DASRecord, dict]) -> str:
 88        # See if it's something we can process, and if not, try digesting
 89        if not self.can_process_record(record):  # BaseModule
 90            return self.digest_record(record)  # BaseModule
 91
 92        if type(record) is DASRecord:
 93            record_fields = record.fields
 94        elif type(record) is dict:
 95            if 'fields' in record:
 96                record_fields = record['fields']
 97            else:
 98                record_fields = record
 99        else:
100            return ('Record passed to FormatTransform was neither a dict nor a '
101                    'DASRecord. Type was %s: %s' % (type(record), str(record)[:80]))
102
103        fields = self.defaults.copy()
104
105        for field, value in record_fields.items():
106            fields[field] = value
107
108        # Add the timestamp as a field as well.
109        if type(record) is DASRecord:
110            fields['timestamp'] = record.timestamp
111        else:
112            fields['timestamp'] = record.get('timestamp', 0)
113
114        # If we're supposed to be outputting USO 8601 timestamps,
115        # convert to appropriate format
116        if self.use_uso_timestamp:
117            fields['timestamp'] = time_str(fields['timestamp'])
118
119        try:
120            result = self.format_str.format(**fields)
121
122        except KeyError:
123            result = None
124
125        if result:
126            return result
127        return None