def _get_params_sub_tree(self, params, name=None): result = OrderedDict({'*': params['*']} if '*' in params else {}) name = name or self.name for key in list(params): self._consume_params_with_brackets(name, params, result, key) self._consume_dot_syntax(name, params, result, key) return result
def __init__(self, name, parent): self.parent = parent self._fields = OrderedDict() self.name = name self._saved = False
class _Template(object): def __init__(self, name, parent): self.parent = parent self._fields = OrderedDict() self.name = name self._saved = False def _pretty_print_fields(self, fields): return ', '.join('%s:%s' % (key, value) for key, value in fields.items()) def _mark_referenced_field(self, field): ref_field = self._get_field_recursive(field.length.field) if not ref_field: raise AssertionError('Length field %s unknown' % field.length.field) ref_field.referenced_later = True def add(self, field): if field.type == 'pdu': self._handle_pdu_field(field) if self._get_field(field.name): raise AssertionError("Duplicate field '%s' in '%s'" % (field.name, self._get_recursive_name())) if field.has_length and field.length.has_references: self._mark_referenced_field(field) self._fields[field.name] = field def _handle_pdu_field(self, field): raise AssertionError('PDU field not allowed') def _get_field(self, field_name): return self._fields.get(field_name) def _get_struct_field(self, field_name): name_split = field_name.split('.', 1) struct_field = self._get_field(name_split[0]) if len(name_split) == 1: return struct_field else: return struct_field._get_struct_field(name_split[1]) def _get_field_recursive(self, field_name): field = self._get_struct_field(field_name) if field: return field else: return self.parent._get_field_recursive(field_name) \ if self.parent else None def _check_params_empty(self, message_fields, name): for key in list(message_fields): if key.startswith('*'): message_fields.pop(key) if message_fields: raise AssertionError("Unknown fields in '%s': %s" % (self._get_recursive_name(), self._pretty_print_fields(message_fields))) def _get_recursive_name(self): return (self.parent._get_recursive_name() + "." if self.parent else '') + self.name def _encode_fields(self, struct, params, little_endian=False): for field in self._fields.values(): encoded = field.encode(params, struct, little_endian=little_endian) # TODO: clean away this ugly hack that makes it possible to skip PDU # (now it is a 0 length place holder in header) if encoded: struct[field.name] = encoded self._check_params_empty(params, self.name) def decode(self, data, parent=None, name=None, little_endian=False): message = self._get_struct(name, parent) data_index = 0 for field in self._fields.values(): message[field.name] = field.decode(data[data_index:], message, little_endian=little_endian) data_index += len(message[field.name]) return message def validate(self, message, message_fields): errors = [] for field in self._fields.values(): errors += field.validate(message, message_fields) self._check_params_empty(message_fields, self.name) return errors def _get_params_sub_tree(self, params, name=None): result = {'*': params['*']} if '*' in params else {} name = name or self.name for key in list(params): prefix, _, ending = key.partition('.') if prefix == name: result[ending] = params.pop(key) elif prefix == '*' and ending: result[ending] = params[key] return result def _get_struct(self, name, parent): return None @property def is_saved(self): return self._saved
class _Template(object): def __init__(self, name, parent): self.parent = parent self._fields = OrderedDict() self.name = name self._saved = False def _pretty_print_fields(self, fields): return ', '.join('%s:%s' % (key, value) for key, value in fields.items()) def _mark_referenced_field(self, field): ref_field = self._get_field_recursive(field.length.field) if not ref_field: raise AssertionError('Length field %s unknown' % field.length.field) ref_field.referenced_later = True def add(self, field): if field.type == 'pdu': self._handle_pdu_field(field) if self._get_field(field.name): raise AssertionError("Duplicate field '%s' in '%s'" % (field.name, self._get_recursive_name())) if field.has_length and field.length.has_references: self._mark_referenced_field(field) self._fields[field.name] = field def _handle_pdu_field(self, field): raise AssertionError('PDU field not allowed') def _get_field(self, field_name): return self._fields.get(field_name) def _get_struct_field(self, field_name): name_split = field_name.split('.', 1) struct_field = self._get_field(name_split[0]) if len(name_split) == 1: return struct_field else: return struct_field._get_struct_field(name_split[1]) def _get_field_recursive(self, field_name): field = self._get_struct_field(field_name) if field: return field else: return self.parent._get_field_recursive(field_name) \ if self.parent else None def _check_params_empty(self, message_fields, name): for key in message_fields.keys(): if key.startswith('*'): message_fields.pop(key) if message_fields: raise AssertionError("Unknown fields in '%s': %s" % (self._get_recursive_name(), self._pretty_print_fields(message_fields))) def _get_recursive_name(self): return (self.parent._get_recursive_name() + "." if self.parent else '') + self.name def _encode_fields(self, struct, params, little_endian=False): for field in self._fields.values(): encoded = field.encode(params, struct, little_endian=little_endian) # TODO: clean away this ugly hack that makes it possible to skip PDU # (now it is a 0 length place holder in header) if encoded: struct[field.name] = encoded self._check_params_empty(params, self.name) def decode(self, data, parent=None, name=None, little_endian=False): message = self._get_struct(name, parent) data_index = 0 for field in self._fields.values(): message[field.name] = field.decode(data[data_index:], message, little_endian=little_endian) data_index += len(message[field.name]) return message def validate(self, message, message_fields): errors = [] for field in self._fields.values(): errors += field.validate(message, message_fields) self._check_params_empty(message_fields, self.name) return errors def _get_params_sub_tree(self, params, name=None): result = {'*': params['*']} if '*' in params else {} name = name or self.name for key in params.keys(): prefix, _, ending = key.partition('.') if prefix == name: result[ending] = params.pop(key) elif prefix == '*' and ending: result[ending] = params[key] return result def _get_struct(self, name, parent): return None @property def is_saved(self): return self._saved