openrvdas.logger.transforms.select_fields_transform
Compute subsamples of input data.
1#!/usr/bin/env python3 2"""Compute subsamples of input data. 3""" 4 5import copy 6import logging 7from typing import Union 8 9from logger.utils.das_record import DASRecord # noqa: E402 10from logger.transforms.transform import Transform # noqa: E402 11 12 13################################################################################ 14class SelectFieldsTransform(Transform): 15 """Cull key:value pairs from a record's field dict. Can accept a 16 top-level dict, a field dict or a DASRecord, and will return a 17 record in the same format as it received. 18 """ 19 20 def __init__(self, keep=None, delete=None, **kwargs): 21 """ 22 ``` 23 keep - an optional list of field names to keep 24 25 delete - an optional list of field names to delete 26 27 One, but not both of these should be present. If both are present, 28 the delete values will be ignored. 29 30 Can accept a top-level dict, a field dict or a DASRecord, and will 31 return a record in the same format as it received. 32 ``` 33 """ 34 super().__init__(**kwargs) # processes 'quiet' and type hints 35 36 self.keep = keep or [] 37 self.delete = delete or [] 38 39 if not keep and not delete: 40 logging.warning('SelectFieldsTransform has empty "keep" and "delete" arguments; ' 41 'no modifications will be made to passed records.') 42 if keep and delete: 43 logging.warning('SelectFieldsTransform has both "keep" and "delete" arguments; ' 44 '"delete" arguments will be ignored.') 45 46 ############################ 47 def transform(self, record: Union[dict, DASRecord]): 48 """ 49 Return a copy of the passed record with the relevant fields kept/deleted. 50 """ 51 # See if it's something we can process, and if not, try digesting 52 if not self.can_process_record(record): # inherited from BaseModule() 53 return self.digest_record(record) # inherited from BaseModule() 54 55 # We need to make a deep copy of the record, because we're going 56 # to modify it as we go, and the same record may be getting passed 57 # to multiple transforms at the same time (e.g., if the transform 58 # is part of a ComposedWriter, and we have multiple 59 # ComposedWriters). 60 new_record = copy.deepcopy(record) 61 62 # Below, we're counting on Python copying the relevant dict by 63 # reference so that if we modify the 'fields' dict, it is also 64 # modified in the record we were passed. 65 66 # As warned in the constructor, if we have both keep and delete, 67 # we're going to pass records through unchanged. 68 if self.keep and self.delete: 69 return new_record 70 71 # If it's a dict, hope it's a single record. 72 elif type(new_record) is DASRecord: 73 fields = new_record.fields 74 75 elif type(new_record) is dict: 76 # If we have a 'fields' dict inside the dict, use that 77 if 'fields' in new_record and type(new_record['fields']) is dict: 78 fields = new_record['fields'] 79 80 # Otherwise treat the entire dict as a field dict 81 else: 82 fields = new_record 83 84 else: 85 logging.warning('SelectFieldsTransform Got non-list/dict/DASRecord ' 86 'record to interpolate: %s', new_record) 87 return None 88 89 if self.delete: 90 for key in self.delete: 91 if key in fields: 92 del fields[key] 93 else: 94 field_list = list(fields.keys()) 95 for key in field_list: 96 if key not in self.keep: 97 del fields[key] 98 99 # If no fields left, scrap the record 100 if not fields: 101 return None 102 103 return new_record
class
SelectFieldsTransform(logger.transforms.transform.Transform):
15class SelectFieldsTransform(Transform): 16 """Cull key:value pairs from a record's field dict. Can accept a 17 top-level dict, a field dict or a DASRecord, and will return a 18 record in the same format as it received. 19 """ 20 21 def __init__(self, keep=None, delete=None, **kwargs): 22 """ 23 ``` 24 keep - an optional list of field names to keep 25 26 delete - an optional list of field names to delete 27 28 One, but not both of these should be present. If both are present, 29 the delete values will be ignored. 30 31 Can accept a top-level dict, a field dict or a DASRecord, and will 32 return a record in the same format as it received. 33 ``` 34 """ 35 super().__init__(**kwargs) # processes 'quiet' and type hints 36 37 self.keep = keep or [] 38 self.delete = delete or [] 39 40 if not keep and not delete: 41 logging.warning('SelectFieldsTransform has empty "keep" and "delete" arguments; ' 42 'no modifications will be made to passed records.') 43 if keep and delete: 44 logging.warning('SelectFieldsTransform has both "keep" and "delete" arguments; ' 45 '"delete" arguments will be ignored.') 46 47 ############################ 48 def transform(self, record: Union[dict, DASRecord]): 49 """ 50 Return a copy of the passed record with the relevant fields kept/deleted. 51 """ 52 # See if it's something we can process, and if not, try digesting 53 if not self.can_process_record(record): # inherited from BaseModule() 54 return self.digest_record(record) # inherited from BaseModule() 55 56 # We need to make a deep copy of the record, because we're going 57 # to modify it as we go, and the same record may be getting passed 58 # to multiple transforms at the same time (e.g., if the transform 59 # is part of a ComposedWriter, and we have multiple 60 # ComposedWriters). 61 new_record = copy.deepcopy(record) 62 63 # Below, we're counting on Python copying the relevant dict by 64 # reference so that if we modify the 'fields' dict, it is also 65 # modified in the record we were passed. 66 67 # As warned in the constructor, if we have both keep and delete, 68 # we're going to pass records through unchanged. 69 if self.keep and self.delete: 70 return new_record 71 72 # If it's a dict, hope it's a single record. 73 elif type(new_record) is DASRecord: 74 fields = new_record.fields 75 76 elif type(new_record) is dict: 77 # If we have a 'fields' dict inside the dict, use that 78 if 'fields' in new_record and type(new_record['fields']) is dict: 79 fields = new_record['fields'] 80 81 # Otherwise treat the entire dict as a field dict 82 else: 83 fields = new_record 84 85 else: 86 logging.warning('SelectFieldsTransform Got non-list/dict/DASRecord ' 87 'record to interpolate: %s', new_record) 88 return None 89 90 if self.delete: 91 for key in self.delete: 92 if key in fields: 93 del fields[key] 94 else: 95 field_list = list(fields.keys()) 96 for key in field_list: 97 if key not in self.keep: 98 del fields[key] 99 100 # If no fields left, scrap the record 101 if not fields: 102 return None 103 104 return new_record
Cull key:value pairs from a record's field dict. Can accept a top-level dict, a field dict or a DASRecord, and will return a record in the same format as it received.
SelectFieldsTransform(keep=None, delete=None, **kwargs)
21 def __init__(self, keep=None, delete=None, **kwargs): 22 """ 23 ``` 24 keep - an optional list of field names to keep 25 26 delete - an optional list of field names to delete 27 28 One, but not both of these should be present. If both are present, 29 the delete values will be ignored. 30 31 Can accept a top-level dict, a field dict or a DASRecord, and will 32 return a record in the same format as it received. 33 ``` 34 """ 35 super().__init__(**kwargs) # processes 'quiet' and type hints 36 37 self.keep = keep or [] 38 self.delete = delete or [] 39 40 if not keep and not delete: 41 logging.warning('SelectFieldsTransform has empty "keep" and "delete" arguments; ' 42 'no modifications will be made to passed records.') 43 if keep and delete: 44 logging.warning('SelectFieldsTransform has both "keep" and "delete" arguments; ' 45 '"delete" arguments will be ignored.')
keep - an optional list of field names to keep
delete - an optional list of field names to delete
One, but not both of these should be present. If both are present,
the delete values will be ignored.
Can accept a top-level dict, a field dict or a DASRecord, and will
return a record in the same format as it received.
def
transform(self, record: Union[dict, logger.utils.das_record.DASRecord]):
48 def transform(self, record: Union[dict, DASRecord]): 49 """ 50 Return a copy of the passed record with the relevant fields kept/deleted. 51 """ 52 # See if it's something we can process, and if not, try digesting 53 if not self.can_process_record(record): # inherited from BaseModule() 54 return self.digest_record(record) # inherited from BaseModule() 55 56 # We need to make a deep copy of the record, because we're going 57 # to modify it as we go, and the same record may be getting passed 58 # to multiple transforms at the same time (e.g., if the transform 59 # is part of a ComposedWriter, and we have multiple 60 # ComposedWriters). 61 new_record = copy.deepcopy(record) 62 63 # Below, we're counting on Python copying the relevant dict by 64 # reference so that if we modify the 'fields' dict, it is also 65 # modified in the record we were passed. 66 67 # As warned in the constructor, if we have both keep and delete, 68 # we're going to pass records through unchanged. 69 if self.keep and self.delete: 70 return new_record 71 72 # If it's a dict, hope it's a single record. 73 elif type(new_record) is DASRecord: 74 fields = new_record.fields 75 76 elif type(new_record) is dict: 77 # If we have a 'fields' dict inside the dict, use that 78 if 'fields' in new_record and type(new_record['fields']) is dict: 79 fields = new_record['fields'] 80 81 # Otherwise treat the entire dict as a field dict 82 else: 83 fields = new_record 84 85 else: 86 logging.warning('SelectFieldsTransform Got non-list/dict/DASRecord ' 87 'record to interpolate: %s', new_record) 88 return None 89 90 if self.delete: 91 for key in self.delete: 92 if key in fields: 93 del fields[key] 94 else: 95 field_list = list(fields.keys()) 96 for key in field_list: 97 if key not in self.keep: 98 del fields[key] 99 100 # If no fields left, scrap the record 101 if not fields: 102 return None 103 104 return new_record
Return a copy of the passed record with the relevant fields kept/deleted.