Классы Record, Field и SubField

Классы Record, Field и SubField предназначены для создания и манипуляции записями, полями и подполями соответственно в клиентском представлении. Они также отвечают за перекодирование записей из серверного представления в клиентское и обратно.

Record

Каждый экземпляр класса Record соответствует одной записи в базе данных ИРБИС и имеет следующие атрибуты:

  • database – имя базы данных, из которой загружена данная запись. Для вновь созданных записей None. После отправки записи на сервер поле database выставляется автоматически.

  • mfn – порядковый номер записи в базе данных. Для вновь созданных записей 0. После отправки записи на сервер поле mfn выставляется автоматически. Диапазон значений для MFN: от 1 до 4294967295. Обратите внимание, при реорганизации базы данных MFN записи может измениться!

  • status – состояние записи: удалена, отсутствует и т. д. Для вновь созданных записей 0. После отправки записи на сервер поле status выставляется автоматически. Обратите внимание, при реорганизации базе данных логически удалённые записи могут пропасть из неё.

  • version – номер версии записи. Для вновь созданных записей 0. При каждой отправке записи на сервер поле version выставляется автоматически. Поле version используется сервером ИРБИС64 для отслеживания конфликтов одновременного обновления записей несколькими клиентами. Обратите внимание, при реорганизации базе данных её версия может измениться!

  • fields – запись содержит произвольное количество полей. Технически их может быть 0, но на практике это означает сбой системы.

При отправке записи на сервер ИРБИС64 тот отсылает обратно клиенту эту же запись со всеми модификациями, которые были проведены над ней сценарием autoin.gbl. При этом могут измениться любые поля записи, а также её статус и версия.

Атрибуты в виде таблицы:

Поле

Тип

Назначение

database

str

Имя базы данных, из которой загружена данная запись.

mfn

int

Номер записи в мастер-файле.

status

int

Статус записи: логически удалена, отсутствует (см. ниже).

version

int

Номер версии записи.

fields

list

Список полей записи.

Статус записи: набор флагов

Имя

Число

Значение

LOGICALLY_DELETED

1

Логически удалена (может быть восстановлена)

PHYSICALLY_DELETED

2

Физически удалена (не может быть восстановлена)

ABSENT

4

Отсутствует

NON_ACTUALIZED

8

Не актуализирована

LAST

32

Последняя версия записи

LOCKED

64

Запись заблокирована на ввод

AUTOIN_ERROR

128

Ошибка в Autoin.gbl.

FULL_TEXT_NOT_ACTUALIZED

256

Полный текст не актуализирован.

Класс Record содержит следующие методы:

  • def __init__(self, *fields) – конструктор, создаёт новый экземпляр записи в памяти клиента. Можно указать поля, которыми будет наполнена запись.

  • def add(self, tag, value = None, *subfields) -> Record – добавляет поле (возможно, со значением и подполями) к записи. Возвращает self, поэтому метод может использоваться в цепочечных вызовах.

  • def add_non_empty(self, tag, value) -> Record – добавляет поле, если его значение не пустое. Возвращает self, поэтому метод может использоваться в цепочечных вызовах.

  • def all(self, tag) -> List[Field] – возвращает список всех полей с указанной меткой.

  • all_as_dict(self, tag: int) -> List[dict] – список полей с указанной меткой, каждое поле в виде словаря «код - значение». Если указанные поля не найдены, возвращается пустой список.

  • def clear(self) -> Record – очистка записи (удаление всех полей).

  • def clone(self) -> Record – создание клона, т. е. полной копии записи. Поля, если присутствуют, тоже клонируются. Возвращает клон записи.

  • def encode(self) -> List[str] – кодирование записи в серверное представление. Инфраструктурный метод, парный к parse.

  • def fm(self, tag, code = „“) -> str – возвращает значение первого поля с указанной меткой (или значение подполя с указанным кодом). Если задан пустой код, то возвращается значение поля до первого разделителя. Если задан код „*“, то возвращается значение до первого разделителя либо значение первого по порядку подполя (смотря, что есть в поле). Если поле с указанной меткой не найдено или нет нужного подполя, возвращается None.

  • def fma(self, tag, code = „“) -> List[str] – возвращает список значений полей с указанной меткой (или значения подполей с указанным кодом). Пустые значения в список не включаются. Если задан пустой код, то возвращаются значения полей до первого разделителя. Если задан код *, то возвращаются значения до первого разделителя либо значения первого по порядку подполя (смотря, что есть в поле). Если нужного подполя в просматриваемом поле нет, в список ничего не добавляется. Если полей с заданной меткой не найдено, возвращается пустой список.

  • def first(self, tag) -> Optional[Field] – возвращает первое поле с указанной меткой либо None.

  • def first_as_dict(self, tag: int) -> dict – возвращает первое из полей с указанной меткой в виде словаря «код - значение». Если указанное поле не найдено, возвращается пустой словарь.

  • def have_field(self, tag) -> bool – выясняет, есть ли в записи поле с указанной меткой.

  • def insert_at(self, index, tag, value = None) -> Field – вставка поля в указанной позиции. Возвращает вставленное поле.

  • def is_deleted(self) -> bool – удалена ли запись?

  • def parse(self, text) – разбор текстового представления записи (в серверном формате). Инфраструктурный метод, парный к encode.

  • def remove_at(self, index) -> Record – удаляет поле в указанной позиции. Возвращает self, поэтому метод может использоваться в цепочечных вызовах.

  • def remove_field(self, tag) -> Record – удаляет поля с указанной меткой. Возвращает self, поэтому метод может использоваться в цепочечных вызовах.

  • def reset(self) -> Record – сбрасывает состояние записи, отвязывая её от базы данных. Поля при этом остаются нетронутыми. Возвращает self, поэтому метод может использоваться в цепочечных вызовах.

  • def set_field(self, tag, value) -> Record – устанавливает значение первого повторения указанного поля. Если указанное значение пустое, поле удаляется из записи. Возвращает self, поэтому метод может использоваться в цепочечных вызовах.

  • def set_subfield(self, tag, code, value) -> Record – устанавливает значение подполя в первом повторении указанного поля. Если указанное значение пустое, подполе удаляется из поля. Возвращает self, поэтому метод может использоваться в цепочечных вызовах.

  • def __iter__(self) – возможность итерироваться по полям.

  • def __iadd__(self, other) – возможность использовать оператор „+=“ для добавления полей.

  • def __isub__(self, other) – возможность использовать оператор „-=“ для удаления полей.

  • def __getitem__(self, item) – возможность получения значения полей с помощью обращения по индексу.

  • def __setitem__(self, key, value) – возможность присваивания значений полей с помощью обращения по индексу.

  • def __len__(self) – количество полей в записи.

  • def __bool__(self) – проверка, не пустая ли запись.

  • def __str__(self) – получение текстового представления записи.

import irbis

SF = irbis.SubField

record = irbis.Record()
record.add(700, SF('a', 'Миронов')) \
    .add('b', 'А. В.') \
    .add('g', 'Алексей Владимирович')
record.add(200, SF('a', 'Заглавие книги')) \
    .add('e', 'Подзаголовочные сведения')
print(f"Заглавие: {record.fm(200, 'a')}")
print(record)

Field

Поле записи характеризуется числовой меткой в диапазоне от 1 до 2147483647 (на практике встречаются коды от 1 до 9999) и содержит значение до первого разделителя (опционально) и произвольное количество подполей (см. класс SubField).

Стандартом MARC у полей предусмотрены также два односимвольных индикатора, но ИРБИС вслед за ISIS их не поддерживает.

Кроме того, стандарт MARC предусматривает т. наз. «фиксированные» поля с метками от 1 до 9 включительно, которые не должны содержать ни индикаторов, ни подполей, но имеют строго фиксированную структуру. ИРБИС такие поля обрабатывает особым образом только в ситуации импорта/экспорта в формат ISO2709, в остальном же он их трактует точно так же, как и прочие поля (которые стандарт называет полями переменной длины).

Стандартом MARC предусмотрены метки в диапазоне от 1 до 999, все прочие являются самодеятельностью ИРБИС. Поля с нестандартными метками не могут быть выгружены в формат ISO2709.

Хотя технически поле может содержать одновременно и значение до первого разделителя, и подполя, но стандартом такая ситуация не предусмотрена, на практике она означает сбой. В стандарте MARC поле содержит либо значение либо подполя.

Начиная с версии 2018, ИРБИС64 резервирует метку 2147483647 для поля GUID - уникального идентификатора записи.

Порядок подполей в поле важен, т. к. на этот порядок завязана обработка т. наз. «вложенных полей».

Стандартом MARC предусмотрено, что внутри поля могут повторяться подполя с одинаковым кодом, однако, ИРБИС вслед за ISIS очень ограниченно поддерживает эту ситуацию (см. форматный выход &umarci).

Класс Field имеет следующие атрибуты:

Поле

Тип

Назначение

tag

int

Тег поля

value

str

Значение поля до первого разделителя

subfields

list

Список подполей

Класс Field содержит следующие методы:

  • def __init__(self, tag = 0, value = None, *subfields) – конструктор, создаёт новый экземпляр поля в памяти клиента. Можно указать подполя, которыми будет наполнено поле.

  • def add(self, code, value = „“) -> Field – добавление подполя с указанным кодом (и, возможно, значением) к записи. Возвращает self, поэтому метод может использоваться в цепочечных вызовах.

  • def add_non_empty(self, code, value) -> Field – добавление подполя с указанным кодом при условии, что значение поля не пустое. Возвращает self, поэтому метод может использоваться в цепочечных вызовах.

  • def all(self, code) -> List[SubField] – возвращает список всех подполей с указанным кодом.

  • def all_values(self, code) -> List[str] – возвращает список значений всех подполей с указанным кодом. Пустые значения подполей в список не включаются.

  • def assign_from(self, other) – присваивание от другого поля. Значение данного поля становится равным значению другого поля. В данное поле помещаются клоны подполей из другого поля. Метка поля не меняется.

  • def clear(self) -> Field – очистка поля. Удаляются все подполя и значение до первого разделителя. Возвращает self, что позволяет использовать метод в цепочечных вызовах.

  • def clone(self) -> Field – создание клона, т. е. полной копии поля. Подполя, если присутствуют, тоже клонируются. Возвращает клон поля.

  • def first(self, code) -> Optional[SubField] – находит первое подполе с указанным кодом, возвращает найденное подполе или None.

  • def first_value(self, code) -> Optional[str] – находит первое подполе с указанным кодом, возвращает значение найденного подполя или None.

  • def get_embedded_fields(self) -> List[Field] – получение списка встроенных полей.

  • def get_value_or_first_subfield(self) -> Optional[str] – выдаёт значение для ^*.

  • def have_subfield(self, code) -> bool – выясняет, есть ли подполе с указанным кодом.

  • def insert_at(self, index: int, code value) -> Field – вставляет подполе в указанную позицию. Возвращает self, поэтому метод может использоваться в цепочечных вызовах.

  • def parse(self, line) – разбор текстового представления поля (в серверном формате). Инфраструктурный метод.

  • def remove_at(self, index) -> Field – удаляет подполе в указанной позиции. Возвращает self, поэтому метод может использоваться в цепочечных вызовах.

  • def remove_subfield(self, code) -> Field – удаляет все подполя с указанным кодом. Возвращает self, поэтому метод может использоваться в цепочечных вызовах.

  • def replace_subfield(self, code, old_value, new_value) -> Field – заменяет значение подполя с указанным кодом. Возвращает self, поэтому метод может использоваться в цепочечных вызовах.

  • def set_subfield(self, code, value) -> Field – устанавливает значение первого повторения подполя с указанным кодом. Если value==None, подполе удаляется. Возвращает self, поэтому метод может использоваться в цепочечных вызовах.

  • def text(self) -> str – Текстовое представление поля без кода.

  • def to_dict(self) -> dict – Выдает словарь «код - значение подполя».

  • def __iter__(self) – возможность итерироваться по подполям.

  • def __iadd__(self, other) – возможность использовать оператор „+=“ для добавления подполей.

  • def __isub__(self, other) – возможность использовать оператор „-=“ для удаления подполей.

  • def __getitem__(self, item) – возможность получения значения подполей с помощью обращения по индексу.

  • def __setitem__(self, key, value) – возможность присваивания значений подполей с помощью обращения по индексу.

  • def __len__(self) – количество подполей в поле.

  • def __bool__(self) – проверка, не пустое ли поле.

  • def __str__(self) – получение текстового представления поля.

import irbis

field = irbis.Field(700)
field.add('a', 'Миронов').add('e', 'А. В.')
field.add('g', 'Алексей Владимирович')
print(field)

SubField

Подполе характеризуется односимвольным кодом (как правило алфавитно-цифровым A-Z, 0-9, но бывают подполя с экзотическими кодами вроде !, ( и др.) и содержит строковое значение (технически может быть пустым, но на практике пустое значение означает сбой).

Коды подполей не чувствительны к регистру. Как правило, ИРБИС приводит коды к верхнему регистру, но это не точно. :)

ИРБИС трактует код подполя „*“ как «значение до первого разделителя либо значение первого по порядку подполя» (смотря по тому, что присутствует в записи).

Поле

Тип

Назначение

code

str

Код подполя (односимвольный!)

value

str

Значение подполя

  • def __init__(self, code = „\0“, value = None) – конструктор, создаёт новый экземпляр подполя в памяти клиента.

  • def assign_from(self, other) – присваивание от другого поля: код и значение берутся от другого подполя.

  • def clone(self) -> SubField – клонирование, т. е. создание точной копии подполя. Возвращает клон подполя.

  • def __bool__(self) – проверка, не пустое ли подполе.

  • def __str__(self) – получение текстового представления подполя.

import irbis

subfield = irbis.SubField('a', 'Подполе A')
print(subfield)

Класс RawRecord

Запись с нераскодированными полями/подполями. Класс определён в irbis.ext и содержит следующие поля:

Поле

Тип

Назначение

database

str

Имя базы данных, из которой загружена данная запись. Для вновь созданных записей None

mfn

int

Номер записи в мастер-файле. Для вновь созданных записей 0

status

int

Статус записи: логически удалена, отсутствует (аналогично Record)

version

int

Номер версии записи

fields

list

Список полей записи в нераскодированном виде (просто строки).

Определены следующие методы:

  • def __init__(self, *fields) – конструктор, создаёт новый экземпляр записи в памяти клиента. Можно указать поля, которыми будет наполнена запись.

  • def clear(self) -> RawRecord – очистка записи (удаление всех полей).

  • def clone(self) -> RawRecord – создание клона, т. е. полной копии записи. Поля, если присутствуют, тоже клонируются. Возвращает клон записи.

  • def encode(self) -> List[str] – кодирование записи в серверное представление. Инфраструктурный метод, парный к parse.

  • def is_deleted(self) -> bool – удалена ли запись?

  • def parse(self, text) – разбор текстового представления записи (в серверном формате). Инфраструктурный метод, парный к encode.

  • def remove_at(self, index) -> Record – удаляет поле в указанной позиции. Возвращает self, поэтому метод может использоваться в цепочечных вызовах.

  • def reset(self) -> Record – сбрасывает состояние записи, отвязывая её от базы данных. Поля при этом остаются нетронутыми. Возвращает self, поэтому метод может использоваться в цепочечных вызовах.

  • def __iter__(self) – возможность итерироваться по полям.

  • def __len__(self) – количество полей в записи.

  • def __bool__(self) – проверка, не пустая ли запись.

  • def __str__(self) – получение текстового представления записи.

Загрузить сырую запись с сервера можно с помощью метода read_raw_record, сохранить на сервере можно с помощью метода write_raw_record.

import irbis

client = irbis.Connection()
client.connect('host', 6666, 'librarian', 'secret')
record = client.read_raw_record(123)
record.fields.append('300#Комментарий к записи')
client.write_raw_record(record)
client.disconnect()