Example #1
0
    def search_read(self, expression: 'Any', limit: int = 0) -> 'List[Record]':
        """
        Поиск и считывание записей.

        :param expression: Поисковый запрос.
        :param limit: Лимит считываемых записей (0 - нет).
        :return: Список найденных записей.
        """
        if not self.check_connection():
            return []

        response = self._search_format_or_read_begin(expression, limit, 'ansi',
                                                     ALL)
        if not response.check_return_code():
            return []

        _ = response.number()
        result = []
        while True:
            line = response.utf()
            if not line:
                break
            lines = line.split("\x1F")
            lines = lines[1:]
            record = Record()
            record.parse(lines)
            result.append(record)
            if limit and len(result) >= limit:
                break
        return result
Example #2
0
    def read_records(self, *mfns: int) -> 'List[Record]':
        """
        Чтение записей с указанными MFN с сервера.

        :param mfns: Перечень MFN
        :return: Список записей
        """
        if not self.check_connection():
            return []

        array = list(mfns)

        if not array:
            return []

        if len(array) == 1:
            record = self.read_record(array[0])
            return [record] if record else []

        lines = self.format_records(ALL, array)
        result: 'List[Record]' = []
        for line in lines:
            parts = line.split(OTHER_DELIMITER)
            if parts:
                parts = [x for x in parts[1:] if x]
                record = Record()
                record.parse(parts)
                if record:
                    record.database = self.database
                    result.append(record)

        return result
Example #3
0
 def decode_record(self) -> Record:
     """
     Декодирование в полноценную запись.
     :return:
     """
     result = Record()
     result.mfn = self.leader.mfn
     result.version = self.leader.version
     result.status = self.leader.status
     for source in self.fields:
         target = Field(source.tag)
         target.headless_parse(source.value)
         result.fields.append(target)
     return result
Example #4
0
def read_text_record(stream) -> 'Optional[Record]':
    """
    Чтение записи из файла в текстовом обменном формате ИРБИС.

    :param stream: Файл
    :return: Запись или None
    """

    result = Record()
    while True:
        line: str = stream.readline()
        if not line:
            break
        line = line.strip()
        if line.startswith(STOP_MARKER):
            break
        if not line.startswith('#'):
            break
        parts = line[1:].split(':', 1)
        if len(parts) != 2:
            break
        tag = int(parts[0])
        text = parts[1][1:]
        field = Field(tag)
        field.parse(text)
        result.fields.append(field)

    if not result.fields:  # Если в записи нет полей, возвращаем None
        return None

    return result
Example #5
0
def read_iso_record(stream, charset: str = ANSI) -> 'Optional[Record]':
    """
    Чтение записи из файла в формате ISO 2709.

    :param stream: Файл или файлоподобный объект
    :param charset: Кодировка
    :return: Декодированная запись либо None
    """

    # Считываем длину записи
    marker = stream.read(5)
    if len(marker) != 5:
        return None

    # а затем и ее остаток
    record_length = parse_int(marker)
    need = record_length - 5
    tail = stream.read(need)
    if len(tail) != need:
        return None

    # Простая проверка, что мы имеем дело с нормальной ISO-записью
    record = marker + tail
    if record[record_length - 1] != RECORD_DELIMITER:
        return None

    # Превращаем запись в Unicode
    indicator_length = parse_int(record[10:11])
    base_address = parse_int(record[12:17])

    # Начинаем собственно конверсию
    result = Record()

    # Пошли по полям при помощи справочника
    directory = MARKER_LENGTH
    while record[directory] != FIELD_DELIMITER:
        # если нарвались на разделитель, значит, справочник закончился

        tag = parse_int(record[directory:directory + 3])
        field_length = parse_int(record[directory + 3:directory + 7])
        field_offset = parse_int(record[directory + 7:directory + 12]) + \
            base_address
        field = Field(tag)
        result.fields.append(field)

        if tag < 10:
            # фиксированное поле
            # не может содержать подполей и индикаторов
            field.value = record[field_offset:field_offset +
                                 field_length - 1].decode(charset)
        else:
            # поле переменной длины
            # содержит два однобайтных индикатора
            # может содержать подполя
            start = field_offset + indicator_length
            stop = field_offset + field_length - indicator_length + 1
            position = start

            # ищем значение поля до первого разделителя
            while position < stop:
                if record[start] == SUBFIELD_DELIMITER:
                    break
                position += 1

            # если есть текст до первого раздлителя, запоминаем его
            if position != start:
                field.value = record[start:position].decode(charset)

            # просматриваем подполя
            start = position
            while start < stop:
                position = start + 1
                while position < stop:
                    if record[position] == SUBFIELD_DELIMITER:
                        break
                    position += 1
                subfield = SubField(chr(record[start + 1]),
                                    record[start + 2:position].decode(charset))
                field.subfields.append(subfield)
                start = position

        # переходим к следующему полю в справочнике
        directory += 12

    return result