def __setitem__(self, key: 'Union[str, int]', value: 'FieldSetItemValue'): if key == '*': self.value = self.validate_value(value) elif isinstance(key, int): if value: if isinstance(value, str): self.subfields[key].value = self.validate_value(value) elif isinstance(value, Field): self.subfields[key] = value elif isinstance(value, (list, tuple)) and len(value) == 2: code, val = value if isinstance(code, str) and isinstance(val, str): self.subfields[key] = SubField(code, val) else: raise TypeError else: self.subfields.pop(key) elif isinstance(key, str): key = SubField.validate_code(key) del self[key] if value is not None: values = key, value self.__bulk_set__(values)
def add(self, code: str, value: 'SubFieldValues' = '')\ -> 'Field': """ Добавление подполя с указанным кодом (и, возможно, значением) к записи. :param code: Код подполя (однобуквенный). :param value: Значение подполя (опционально). :return: Self """ code = SubField.validate_code(code) if code == '*': if value and isinstance(value, (list, tuple)): value = value[0] if not self.value: self.value = self.validate_value(value) else: raise ValueError('Значение до первого разделителя уже задано') else: if value: if isinstance(value, str): value = [value] for val in value: subfield = SubField(code, val) self.subfields.append(subfield) return self
def have_subfield(self, code: str) -> bool: """ Выясняет, есть ли подполе с указанным кодом. :param code: Искомый код подполя (должен быть однобуквенным). :return: True, если есть хотя бы одно подполе с указанным кодом. """ code = SubField.validate_code(code) return code in self.keys()
def all(self, code: str) -> 'FieldGetReturn': """ Список всех подполей с указанным кодом. :param code: Код подполя (однобуквенный). :return: Список подполей (возможно, пустой). """ code = SubField.validate_code(code) return self.get(code)
def __delitem__(self, key: 'Union[str, int]'): """ Метод удаления всех подполей с указанным кодом. Может вызываться следующим образом -- del field[key]. :param key: строковый код :return: """ if isinstance(key, int): self.subfields.pop(key) elif isinstance(key, str): key = SubField.validate_code(key) self.subfields = [sf for sf in self.subfields if sf.code != key]
def all_values(self, code: str) -> 'List[str]': """ Список значений всех подполей с указанным кодом. Пустые значения подполей в список не включаются. :param code: Код подполя (однобуквенный). :return: Список значений (возможно, пустой). """ code = SubField.validate_code(code) if code == '*': return [self.get_value_or_first_subfield() or ''] return [sf.value for sf in self.subfields if sf.code == code if sf.value]
def add_non_empty(self, code: str, value: 'Optional[str]') -> 'Field': """ Добавление подполя с указанным кодом при условии, что значение поля не пустое. :param code: Код подполя (однобуквенный). :param value: Значение подполя (опциональное). :return: Self """ code = SubField.validate_code(code) if value: self.add(code, value) return self
def insert_at(self, index: int, code: str, value: str) -> 'Field': """ Вставляет подполе в указанную позицию. :param index: Позиция для вставки. :param code: Код подполя (обязательно). :param value: Значение подполя (опционально). :return: Self """ assert index >= 0 code = SubField.validate_code(code) subfield = SubField(code, value) self.subfields.insert(index, subfield) return self
def replace_subfield(self, code: str, old_value: 'Optional[str]', new_value: 'Optional[str]') -> 'Field': """ Заменяет значение подполя с указанным кодом. :param code: Код подполя (обязательно). :param old_value: Старое значение. :param new_value: Новое значение. :return: Self. """ code = SubField.validate_code(code) for subfield in self.subfields: if subfield.code == code and subfield.value == old_value: subfield.value = new_value return self
def first_value(self, code: str, default: 'Optional[str]' = None)\ -> 'Optional[str]': """ Находит первое подполе с указанным кодом и выдает его значение. :param code: Искомый код. :param default: Значение по умолчанию. :return: Значение подполя или значение по умолчанию. """ code = SubField.validate_code(code) if code == '*': return self.get_value_or_first_subfield() for subfield in self.subfields: if subfield.code == code: return subfield.value return default
def first(self, code: str, default: 'Optional[SubField]' = None)\ -> 'Optional[Union[SubField, Value]]': """ Находит первое подполе с указанным кодом. :param code: Искомый код. :param default: Значение по умолчанию. :return: Подполе, значение до разделителя или default. """ code = SubField.validate_code(code) result = self.get(code) if result: if isinstance(result, list): return result[0] return result return default
def __getitem__(self, key: 'Union[str, int]')\ -> 'FieldGetReturn': """ Получение значения подполя по индексу :param key: строковый код или позиция подполя :return: список подполей, подполе или строка """ if key == '*': if self.value: return self.value elif isinstance(key, str): code = SubField.validate_code(key) return [sf for sf in self.subfields if sf.code == code] elif isinstance(key, int): return self.subfields[key] raise KeyError
def set_subfield(self, code: str, value: 'Optional[str]') -> 'Field': """ Устанавливает значение первого повторения подполя с указанным кодом. Если value==None, подполе удаляется. :param code: Код искомого подполя. :param value: Устанавливаемое значение подполя (опционально). :return: Self """ code = SubField.validate_code(code) if value: found = self.first(code) if found: if isinstance(found, str): self.value = value elif isinstance(found, SubField): found.value = value else: self.add(code, value) else: return self.remove_subfield(code) return self