1c-bsp-api
Справочник программного интерфейса Библиотеки стандартных подсистем (БСП) 1С - какие общие модули существуют, какие у них экспортные методы, сигнатуры, типы параметров, контексты выполнения и переопределяемые обработчики. Используй когда пишешь код на конфигурации с БСП и нужно у
Install
npx skills add https://github.com/Desko77/claude-code-skills-1c/tree/main/skills/1c-bsp-api
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install desko77-claude-code-skills-1c@llmmart
git clone https://github.com/Desko77/claude-code-skills-1c.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole desko77/claude-code-skills-1c collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
Справочник API БСП
Офлайн-справочник по программному интерфейсу БСП: 2624 метода в 284 модулях, 71 подсистема, версии 3.1.11 и 3.2.1. Собран из двух источников одновременно - структура и сигнатуры из документации, модули и экспортность из самой библиотеки. Каждая версия документации сведена со своим дистрибутивом, поэтому различия между версиями видны, а не усреднены.
Назначение написано нами: одна строка у каждого из 284 модулей и у 440 методов ядра. Описательный текст документации ИТС в справочник не переносится.
Справочник больше мегабайта, в контекст целиком не грузится. Он спрашивается по месту.
Главное правило
Не пиши вызов метода БСП, не проверив его. Имена в БСП длинные и составные, поэтому
правдоподобная выдумка выглядит как настоящее имя. Классические несуществующие:
ФайловаяСистемаКлиентСервер, JSONСтрокой, Пользователи.СсылкаТекущегоПользователя.
python skills/1c-bsp-api/scripts/bsp-api.py check ФайловаяСистемаКлиентСервер.ПолучитьФайл
Код возврата 1, если вызова нет. При промахе инструмент подсказывает похожие имена - и по модулю, и по методу.
Как устроена библиотека
Суффикс имени модуля - это контекст выполнения, а не тематика. Один механизм разложен по нескольким модулям, и выбор между ними определяется тем, откуда идет вызов:
| Суффикс | Где исполняется | Пример |
|---|---|---|
без суффикса или Сервер |
сервер, толстый клиент, внешнее соединение | ОбщегоНазначения |
Клиент |
тонкий и толстый клиент | ОбщегоНазначенияКлиент |
КлиентСервер |
и там, и там | ОбщегоНазначенияКлиентСервер |
ВызовСервера |
сервер, вызывается с клиента напрямую | ОбщегоНазначенияВызовСервера |
Отсюда частая ошибка: серверный метод вызывают из клиентского кода. Контекст каждого метода есть
в справочнике, отбор - ключом --av (S сервер, T тонкий, F толстый, E внешнее
соединение, C вызов сервера).
Три вида модулей по назначению:
- Обычные - публичный интерфейс, их и вызывают:
ОбщегоНазначения,Пользователи,УправлениеПечатью. Переопределяемый- точки расширения. Их не вызывают, в них ПИШУТ: обработчик вызывает библиотека, а тело пишет внедряющая конфигурация. Таких методов 372.Служебный- внутренняя реализация библиотеки. В программный интерфейс не входит ни один служебный метод, и вызывать их нельзя: они меняются между версиями без объявления.
Еще два суффикса встречаются реже: ПовтИсп - модуль с повторным использованием возвращаемых
значений, Локализация - национальная специфика.
Часть интерфейса объявлена не в общих модулях. Обмен данными опубликован модулями объектов
обработок (Обработка.УниверсальныйОбменДаннымиXML, Обработка.КонвертацияОбъектовXDTO).
В справочнике они есть наравне с общими модулями.
Запросы
B=skills/1c-bsp-api/scripts/bsp-api.py
python $B find печать # поиск по имени, модулю, подсистеме, назначению
python $B find "реквизит объект" # ищутся все слова запроса сразу, не подстрока
python $B find файл --av T # только то, что доступно на тонком клиенте
python $B show ОбщегоНазначения.ЗначениеРеквизитаОбъекта # карточка метода
python $B show ЗначениеРеквизитаОбъекта # все модули, где есть метод с таким именем
python $B module Пользователи # состав модуля целиком
python $B modules контакт # какие вообще есть модули
python $B subsystem печать # модули и механизмы подсистемы
python $B overrides обновлен # переопределяемые обработчики под задачу
python $B check Пользователи.ТекущийПользователь
python $B stats # что вообще в справочнике
Общие ключи отбора: --av, --sub <подсистема>, --version 3.2.1, --limit N.
Как читать выдачу
Строка вида ОбщегоНазначения.ЗначениеРеквизитаОбъекта SFE - это модуль, метод и контексты.
Пометка [?] означает, что модуль выведен, а не подтвержден. Документация БСП называет
механизм, а не модуль, поэтому у части методов модуль восстановлен по примеру вызова или по
совпадению контекстов. В карточке (show) последняя строка всегда говорит, откуда взято имя
модуля. Метод с пометкой перед использованием стоит сверить с конфигурацией проекта.
Пометка стоит у 117 методов из 2624, это около четырех процентов. Еще у 37 модуль определить
не удалось вовсе - они собраны под именем ?. Это не значит, что метода нет: значит, одно и то же
имя объявлено в нескольких модулях, и документация не говорит, о каком из них статья.
Пометка [!] означает, что между версиями метод изменился. Карточка тогда содержит строку
"ВНИМАНИЕ, в <версия> иначе" с прежней сигнатурой. Таких методов 27, и часть изменений ломающие:
ОбщегоНазначения.ВыполнитьМетодКонфигурации из процедуры стал функцией, а у
ДобавитьПоказатель новый параметр вставлен не в конец, а первым. Код, написанный по новой
сигнатуре, на старой версии передаст аргументы не туда и об этом не сообщит.
Частые ошибки
- Выдуманный модуль. Проверять
check, а не полагаться на память. - Серверный метод в клиентском коде. Смотреть контексты; для клиента почти всегда есть
парный модуль с суффиксом
Клиент. - Вызов служебного модуля. Если в имени есть
Служебный- это не интерфейс. - Попытка вызвать переопределяемый обработчик. В него пишут тело, а не вызывают его.
- Метод из другой версии. У каждой записи указано, в каких версиях БСП она есть. Метод,
помеченный только
3.2.1, на 3.1.11 не существует. А метод с пометкой[!]существует в обеих, но вызывается по-разному - смотреть карточку до того, как писать вызов. - Расчет на то, что у метода тот же набор параметров, что был раньше. Сигнатура в справочнике полная, включая значения по умолчанию - брать оттуда.
Границы
Справочник знает ИМЕНА, СИГНАТУРЫ и КОНТЕКСТЫ, а назначение - строкой, написанной нами. Развернутого
описания в нем нет: текст документации ИТС лицензионный и сюда не переносится. Строка назначения есть
у каждого модуля, но у методов пока только у ядра - базовых модулей ОбщегоНазначения*, длительных
операций, пользователей, строковых функций, файловой системы и журнала регистрации. Когда нужно
понять механизм глубже, а не форму вызова - идти в документацию ИТС по подсистеме, которую покажет
subsystem.
Не покрыты: HTTP-сервисы и веб-сервисы библиотеки, макеты, роли, права, состав метаданных подсистем. Только программный интерфейс кода.
Сборка справочника
Готовый справочник лежит в references/bsp-api.jsonl и обновлять его нужно только при переходе
на новую версию БСП. Пересборка требует двух источников, оба лицензионные и в репозиторий не
входят: скрапа документации с ИТС и дистрибутива библиотеки.
python -m v8unpack -E 1Cv8.cf E:\bsp\3_2_1 --temp E:\bsp\_tmp # распаковать дистрибутив
python skills/1c-bsp-api/scripts/bsp-build.py \
--docs "3.1.11=E:\scrape\bsp3111doc" --docs "3.2.1=E:\scrape\bsp321doc" \
--lib "3.1.11=E:\bsp\3_1_11" --lib "3.2.1=E:\bsp\3_2_1" \
--purposes skills/1c-bsp-api/references/purposes.json \
--out skills/1c-bsp-api/references/bsp-api.jsonl \
--map skills/1c-bsp-api/references/subsystem-map.md
Формулировки назначения ведутся отдельно, в references/purposes.json: раздел modules и раздел
methods с ключами вида Модуль.Метод. При сборке они подмешиваются в справочник, а имена, которых
в нем нет, генератор называет в отчете - это ловит и опечатку, и формулировку к методу, которого
в этой версии уже не существует.
Ключи --docs и --lib указываются по одному на версию и связываются префиксом. Связывать
обязательно: если сшивать документацию 3.1.11 с библиотекой 3.2.1, методы, убранные в новой
версии, будут объявлены несуществующими. Библиотека без префикса версии берется для всех.
Брать надо 1Cv8.cf - чистую библиотеку, а не 1Cv8_demo.cf: демонстрационная конфигурация
несет объекты, которых в поставке нет. Распаковка идет без платформы и Конфигуратора.
Скрипты на Python, PowerShell-порта нет: сборка нужна редко, а поиск идет по готовому файлу.
Files (claude-code-skills-1c)
-
evals
-
evals.json 6 KB
{ "skill_name": "1c-bsp-api", "_": "Поведенческие кейсы. Гоняются через tools/run_skill_evals.py: фаза RED без скила, фаза GREEN со скилом. Поля expect и forbid - регулярные выражения по тексту ответа, checks_bsl включает сверку вызовов в блоках BSL с офлайн-справочником БСП. Все имена модулей и методов в кейсах проверены по самому справочнику.", "evals": [ { "id": "invented-module-refused", "prompt": "На конфигурации с БСП мне нужно получить файл с диска. Коллега советует вызвать ФайловаяСистемаКлиентСервер.ПолучитьФайл. Напиши, как это правильно сделать, и покажи код на BSL.", "expected_output": "Агент сообщает, что общего модуля ФайловаяСистемаКлиентСервер в БСП нет, вместо выдумывания сигнатуры несуществующего метода.", "expectations": [ "Прямо сказано, что модуля ФайловаяСистемаКлиентСервер не существует", "Не приведена выдуманная сигнатура ПолучитьФайл у этого модуля" ], "expect": [ "ФайловаяСистемаКлиентСервер" ], "forbid": [ "ФайловаяСистемаКлиентСервер\\s*\\.\\s*ПолучитьФайл\\s*\\(" ], "checks_bsl": true }, { "id": "current-user-thin-client", "prompt": "Напиши обработчик команды формы на BSL: в клиентской процедуре с директивой НаКлиенте нужно показать имя текущего пользователя. Конфигурация с БСП, работаем в тонком клиенте.", "expected_output": "Использован ПользователиКлиент.ТекущийПользователь, доступный на тонком клиенте, а не серверный модуль Пользователи.", "expectations": [ "Клиентский код обращается к модулю с суффиксом Клиент", "Серверный модуль Пользователи не вызывается напрямую из НаКлиенте" ], "expect": [ "ПользователиКлиент\\s*\\.\\s*ТекущийПользователь" ], "checks_bsl": true }, { "id": "overridable-is-implemented-not-called", "prompt": "На конфигурации с БСП нужно выполнить свой код сразу после обновления информационной базы на новую версию. Покажи на BSL, куда его поместить.", "expected_output": "Указан переопределяемый обработчик ОбновлениеИнформационнойБазыПереопределяемый.ПослеОбновленияИнформационнойБазы как точка реализации, а не как вызов из прикладного кода.", "expectations": [ "Назван модуль ОбновлениеИнформационнойБазыПереопределяемый", "Сказано, что обработчик реализуют, а не вызывают" ], "expect": [ "ОбновлениеИнформационнойБазыПереопределяемый" ], "checks_bsl": true }, { "id": "message-bound-to-field", "prompt": "Напиши на BSL серверную проверку заполнения реквизита Контрагент в модуле объекта документа. Если реквизит пуст, покажи пользователю сообщение, привязанное к полю, и установи Отказ. Конфигурация с БСП.", "expected_output": "Использован ОбщегоНазначения.СообщитьПользователю с привязкой к полю и параметром Отказ, а не конструктор платформы.", "expectations": [ "Вызван ОбщегоНазначения.СообщитьПользователю", "Передано поле и Отказ", "Не использован Новый СообщениеПользователю" ], "expect": [ "ОбщегоНазначения\\s*\\.\\s*СообщитьПользователю\\s*\\(", "Отказ" ], "forbid": [ "Новый\\s+СообщениеПользователю" ], "checks_bsl": true }, { "id": "invented-current-user-property", "prompt": "Конфигурация с БСП. Нужна ссылка на элемент справочника Пользователи для текущего сеанса на сервере. Покажи вызов на BSL.", "expected_output": "Использована функция Пользователи.ТекущийПользователь. Несуществующая Пользователи.СсылкаТекущегоПользователя не появляется.", "expectations": [ "Вызвана существующая функция модуля Пользователи", "Не выдумано имя СсылкаТекущегоПользователя" ], "expect": [ "Пользователи\\s*\\.\\s*ТекущийПользователь" ], "forbid": [ "СсылкаТекущегоПользователя" ], "checks_bsl": true } ] }
-
-
references
-
bsp-api.jsonl 1.7 MB · in bundle
-
purposes.json 141.6 KB
{ "_": "Формулировки назначения своими словами. Единственная часть справочника, написанная нами, а не выведенная из источников. Раздел modules отвечает на вопрос куда идти, раздел methods - что взять.", "modules": { "?": "Метод документирован, но однозначно определить его модуль не удалось: одно и то же имя объявлено в нескольких модулях. Смотреть подсистему и механизм в карточке", "АвтономнаяРабота": "Автономное рабочее место: работа без постоянной связи с основной базой и синхронизация при подключении", "АдминистрированиеКластера": "Управление кластером серверов из кода: сеансы и соединения информационной базы, блокировка сеансов и регламентных заданий, профили безопасности", "АдресныйКлассификатор": "Государственный адресный реестр: загруженные регионы, поиск адресных объектов, коды и наименования, проверка адреса по классификатору", "АдресныйКлассификаторКлиент": "Клиентская часть адресного классификатора: загрузка и выбор адресных объектов", "БизнесПроцессыИЗадачиКлиент": "Клиентская часть бизнес-процессов и задач: команды работы с процессами и задачами на форме", "БизнесПроцессыИЗадачиКлиентПереопределяемый": "Клиентская точка расширения бизнес-процессов", "БизнесПроцессыИЗадачиКлиентСервер": "Общие правила работы с бизнес-процессами и задачами", "БизнесПроцессыИЗадачиПереопределяемый": "Точка расширения бизнес-процессов: свои объекты адресации, свои правила заполнения задач", "БизнесПроцессыИЗадачиСервер": "Бизнес-процессы и задачи: создание и старт процессов, адресация и исполнители задач, отложенный старт, выполнение задач", "БлокировкаРаботыСВнешнимиРесурсамиПереопределяемый": "Точка расширения блокировки работы с внешними ресурсами в копии базы", "ВариантыОтчетов": "Варианты отчетов и их размещение в интерфейсе: регистрация вариантов, настройка размещения по подсистемам, пользовательские варианты", "ВариантыОтчетовКлиент": "Клиентская часть вариантов отчетов: открытие и настройка варианта", "ВариантыОтчетовКлиентСервер": "Общие имена и правила работы с вариантами отчетов", "ВариантыОтчетовПереопределяемый": "Точка расширения вариантов отчетов: свои варианты и их размещение", "ВерсионированиеОбъектов": "История изменений объектов: хранение версий, сравнение версий, отчет по изменениям", "ВерсионированиеОбъектовКлиент": "Клиентская часть версионирования: открытие истории изменений объекта", "ВерсионированиеОбъектовПереопределяемый": "Точка расширения версионирования: какие объекты версионировать и как", "ВерсионированиеОбъектовСобытия": "Обработчики подписок на события, записывающие версию объекта при изменении", "Взаимодействия": "Письма, звонки, встречи и планируемые взаимодействия с контактами", "ВзаимодействияКлиент": "Клиентская часть взаимодействий: создание и просмотр писем, звонков и встреч", "ВзаимодействияКлиентСервер": "Общие правила работы с взаимодействиями", "ВзаимодействияКлиентСерверПереопределяемый": "Точка расширения взаимодействий, общая для клиента и сервера", "ВзаимодействияЛокализация": "Национальная специфика взаимодействий", "ВзаимодействияПереопределяемый": "Точка расширения взаимодействий: свои виды контактов", "ВнешниеКомпонентыКлиент": "Подключение и установка внешних компонент на рабочем месте", "ВнешниеКомпонентыКлиентЛокализация": "Национальная специфика внешних компонент на клиенте", "ВнешниеКомпонентыСервер": "Хранение и выдача внешних компонент с сервера", "ВнешниеПользователи": "Внешние пользователи - контрагенты, партнеры, физические лица, работающие в программе через отдельный вид учетных записей", "ВнешниеПользователиКлиент": "Клиентская часть работы с внешними пользователями", "ВыгрузкаОбъектовВФайлы": "Выгрузка объектов конфигурации в файлы для последующей загрузки", "ГенерацияШтрихкода": "Формирование изображений штрихкодов и QR-кодов", "ГрафикиРаботы": "Графики работы организации: рабочее время по дням, расчет длительности с учетом графика", "ГрупповоеИзменениеОбъектовКлиент": "Клиентская часть группового изменения объектов", "ГрупповоеИзменениеОбъектовПереопределяемый": "Точка расширения группового изменения: какие объекты и реквизиты доступны", "ДатыЗапретаИзменения": "Запрет изменения данных до указанной даты: проверка при записи, разделы и объекты запрета", "ДатыЗапретаИзмененияПереопределяемый": "Точка расширения дат запрета: свои разделы запрета", "ДлительныеОперации": "Выполнение долгих действий в фоновом задании: запуск процедуры или функции в фоне, ожидание результата, сообщение о ходе выполнения, выполнение в несколько потоков", "ДлительныеОперацииКлиент": "Клиентская часть длительных операций: ожидание завершения фонового задания и показ хода выполнения пользователю", "ДополнительныеОтчетыИОбработки": "Дополнительные отчеты и обработки, подключаемые пользователем: регистрация, права, назначение объектам, запуск", "ДополнительныеОтчетыИОбработкиКлиент": "Клиентская часть дополнительных отчетов и обработок: выполнение команд", "ДополнительныеОтчетыИОбработкиКлиентПереопределяемый": "Клиентская точка расширения дополнительных отчетов и обработок", "ДополнительныеОтчетыИОбработкиКлиентСервер": "Общие имена видов, типов команд и форм для дополнительных отчетов и обработок", "ДополнительныеОтчетыИОбработкиПереопределяемый": "Точка расширения дополнительных отчетов и обработок", "ЖурналРегистрации": "Запись событий в журнал регистрации и чтение журнала на сервере", "ЖурналРегистрацииКлиент": "Запись клиентских событий в журнал регистрации", "ЗагрузкаДанныхИзФайла": "Загрузка табличных данных из файла в объекты конфигурации: разбор, сопоставление колонок, запись", "ЗагрузкаДанныхИзФайлаКлиент": "Клиентская часть загрузки данных из файла", "ЗагрузкаДанныхИзФайлаКлиентСервер": "Общие правила разбора загружаемых данных", "ЗагрузкаДанныхИзФайлаПереопределяемый": "Точка расширения загрузки из файла: свои объекты-приемники", "ЗаметкиПользователя": "Личные заметки пользователя к объектам и разделам", "ЗаполнениеОбъектовПереопределяемый": "Точка расширения команд заполнения объектов", "ЗапретРедактированияРеквизитовОбъектов": "Запрет правки ключевых реквизитов после проведения или использования объекта", "ЗапретРедактированияРеквизитовОбъектовКлиент": "Клиентская часть запрета редактирования реквизитов: разблокировка на форме", "ЗапретРедактированияРеквизитовОбъектовПереопределяемый": "Точка расширения запрета редактирования: свои запрещенные реквизиты", "ЗащитаПерсональныхДанных": "Учет доступа к персональным данным и их уничтожение: журнал событий доступа, встраивание в формы объектов", "ЗащитаПерсональныхДанныхКлиент": "Клиентская часть защиты персональных данных", "ЗащитаПерсональныхДанныхПереопределяемый": "Точка расширения защиты персональных данных: свои объекты с персональными данными", "ЗаявлениеНаСертификатПереопределяемый": "Точка расширения заявлений на выпуск сертификата", "ИнтеграцияПодсистемБСП": "Связывает подсистемы БСП между собой и с встраивающей конфигурацией: объявление состава подсистем и условные вызовы между ними", "ИнтерфейсODataПереопределяемый": "Точка расширения интерфейса OData: состав публикуемых объектов", "ИнформацияПриЗапускеПереопределяемый": "Точка расширения информационных сообщений при запуске программы", "КалендарныеГрафики": "Производственный календарь и календарные графики: рабочие и нерабочие дни, сдвиг даты на рабочие дни, ближайшая рабочая дата", "КалендарныеГрафикиЛокализация": "Национальная специфика производственного календаря", "КалендарныеГрафикиПереопределяемый": "Точка расширения календарных графиков: свои производственные календари", "КонструкторФормул": "Конструктор выражений над данными объекта: сбор доступных полей, проверка и вычисление формулы", "КонструкторФормулКлиент": "Клиентская часть конструктора формул: открытие конструктора и правка выражения", "КонтрольВеденияУчета": "Проверки корректности данных: запуск проверок, регистрация проблем, отчет по найденным проблемам", "КонтрольВеденияУчетаКлиент": "Клиентская часть контроля ведения учета: открытие отчета по проблемам", "КонтрольВеденияУчетаПереопределяемый": "Точка расширения контроля учета: свои виды проверок", "КонтрольРаботыПользователей": "Отчеты о действиях пользователей по данным журнала регистрации", "МашиночитаемыеДоверенностиФНС": "Машиночитаемые доверенности ФНС: формирование, подписание, регистрация и проверка", "МашиночитаемыеДоверенностиФНСКлиент": "Клиентская часть машиночитаемых доверенностей", "МашиночитаемыеДоверенностиФНСКлиентПереопределяемый": "Клиентская точка расширения машиночитаемых доверенностей", "МашиночитаемыеДоверенностиФНСПереопределяемый": "Точка расширения машиночитаемых доверенностей", "МультиязычностьКлиент": "Клиентская часть многоязычности", "МультиязычностьКлиентСервер": "Общие правила работы с многоязычными данными на клиенте и сервере", "МультиязычностьПереопределяемый": "Точка расширения многоязычности: свои языки и свои многоязычные реквизиты", "МультиязычностьСервер": "Многоязычные данные: реквизиты на разных языках, подстановка языка в запросы и представления", "НапоминанияПользователя": "Напоминания пользователю о событиях и объектах: создание, перенос, отключение", "НапоминанияПользователяКлиент": "Клиентская часть напоминаний: показ и откладывание напоминания", "НапоминанияПользователяКлиентСервер": "Общие правила расчета времени напоминания", "НапоминанияПользователяПереопределяемый": "Точка расширения напоминаний: свои источники событий", "НастройкаПорядкаЭлементов": "Ручной порядок элементов в списках: перемещение вверх и вниз, реквизит упорядочивания", "НастройкиПрограммыПереопределяемый": "Точка расширения формы настроек программы: свои разделы и элементы настроек", "ОбменДаннымиXDTOСервер": "Универсальный формат обмена: отправка и получение данных, инициализация обмена, поиск правил конвертации, протокол", "ОбменДаннымиВМоделиСервиса": "Обмен данными в модели сервиса: особенности синхронизации между областями данных", "ОбменДаннымиВМоделиСервисаПереопределяемый": "Точка расширения обмена в модели сервиса", "ОбменДаннымиВнешнееСоединение": "Обмен через внешнее соединение с другой информационной базой", "ОбменДаннымиВызовСервера": "Функции обмена данными, вызываемые с клиента напрямую", "ОбменДаннымиКлиент": "Клиентская часть синхронизации данных: команды запуска обмена и просмотра результатов", "ОбменДаннымиПереопределяемый": "Точка расширения обмена данными: свои планы обмена, свои правила регистрации и конвертации", "ОбменДаннымиРегистрацияСервер": "Регистрация изменений объектов для узлов обмена на стороне сервера", "ОбменДаннымиСервер": "Синхронизация данных между информационными базами: настройки узлов и подключений, запуск и мониторинг обмена, регистрация изменений", "ОбменДаннымиСобытия": "Обработчики событий правил регистрации и конвертации при обмене данными", "ОбновлениеИнформационнойБазы": "Механизм обновления данных при переходе на новую версию: регистрация обработчиков обновления, порционная обработка ссылок и наборов записей, отложенное обновление, отметки об обработанных данных, начальное заполнение", "ОбновлениеИнформационнойБазыКлиентПереопределяемый": "Клиентские точки расширения обновления: что показать пользователю до и после перехода на новую версию", "ОбновлениеИнформационнойБазыПереопределяемый": "Точка расширения обновления: здесь конфигурация объявляет свои обработчики обновления и порядок их выполнения", "ОбновлениеКонфигурации": "Обновление конфигурации из файла или с сервиса обновлений", "ОбновлениеКонфигурацииКлиент": "Клиентская часть обновления конфигурации: помощник и перезапуск", "Обработка.КонвертацияОбъектовXDTO (модуль объекта)": "Конвертация объектов по правилам формата XDTO при обмене данными", "Обработка.КонвертацияОбъектовИнформационныхБаз (модуль объекта)": "Конвертация объектов при обмене между информационными базами: выгрузка, загрузка, правила", "Обработка.РегистрацияИзмененийДляОбменаДанными (модуль объекта)": "Регистрация и снятие регистрации изменений объектов для узлов обмена", "Обработка.ТранспортСообщенийОбменаESB1C (модуль менеджера)": "Транспорт сообщений обмена через шину 1С:Шина", "Обработка.УниверсальныйОбменДаннымиXML (модуль объекта)": "Универсальный обмен данными XML: выгрузка и загрузка по правилам обмена, разбор сообщения, счетчики и протокол. В дистрибутиве 3.2.1 обработки уже нет", "Обсуждения": "Обсуждения и сообщения через систему взаимодействия", "ОбсужденияКлиент": "Клиентская часть обсуждений", "ОбсужденияЛокализация": "Национальная специфика обсуждений", "ОбщегоНазначения": "Базовый серверный модуль библиотеки: чтение реквизитов объектов без чтения самих объектов, работа с метаданными и ссылками, свойства сеанса и окружения, выполнение стороннего кода в безопасном режиме, хранилища настроек, обращения в интернет", "ОбщегоНазначенияКлиент": "Базовые клиентские операции: свойства сеанса на стороне клиента, оповещения об изменении объектов, подключение внешних компонент, типовые диалоги подтверждения и правки текста, резервное копирование", "ОбщегоНазначенияКлиентПереопределяемый": "Клиентские точки расширения ядра: свои действия при старте и завершении работы, обработка навигационных ссылок", "ОбщегоНазначенияКлиентСервер": "Базовые операции, доступные и на клиенте: коллекции и структуры, разбор и сборка путей и имен файлов, отборы динамических списков, сообщения пользователю, проверка адресов электронной почты", "ОбщегоНазначенияПереопределяемый": "Точки расширения ядра: подключение своих подсистем к общим механизмам, свои параметры работы программы, переименования объектов метаданных при обновлении", "ОрганизацииПереопределяемый": "Точка расширения организаций: свои источники сведений об организации", "ОрганизацииСервер": "Сведения об организациях: реквизиты, ответственные лица, обособленные подразделения, индивидуальные предприниматели", "ОтправкаSMS": "Отправка SMS через настроенного оператора: текст, получатели, статус доставки", "ОтправкаSMSКлиент": "Клиентская часть отправки SMS", "ОтправкаSMSКлиентПереопределяемый": "Клиентская точка расширения отправки SMS", "ОтправкаSMSПереопределяемый": "Точка расширения отправки SMS: свой оператор", "ОтчетОДвиженияхДокументаПереопределяемый": "Точка расширения отчета о движениях документа", "ОтчетыКлиент": "Клиентская часть общих механизмов отчетов", "ОтчетыКлиентПереопределяемый": "Клиентская точка расширения форм отчетов", "ОтчетыКлиентСервер": "Общие для клиента и сервера правила работы с настройками отчетов", "ОтчетыПереопределяемый": "Точка расширения общих механизмов отчетов", "ОтчетыСервер": "Общие механизмы отчетов: настройки компоновки, параметры формирования, расширения форм отчетов", "ОценкаПроизводительности": "Замеры времени ключевых операций и выгрузка результатов для анализа", "ОценкаПроизводительностиКлиент": "Клиентская часть замеров: начало и завершение замера ключевой операции", "ПереводТекстаНаДругиеЯзыки": "Перевод текста через внешний сервис перевода", "ПереводТекстаНаДругиеЯзыкиЛокализация": "Национальная специфика перевода текста", "ПодключаемыеКоманды": "Команды, добавляемые к формам объектов другими подсистемами: сбор состава команд и их размещение", "ПодключаемыеКомандыКлиент": "Клиентская часть подключаемых команд: выполнение команды на форме", "ПодключаемыеКомандыКлиентСервер": "Общие правила работы с подключаемыми командами", "ПодключаемыеКомандыПереопределяемый": "Точка расширения подключаемых команд: свои команды для форм объектов", "ПодсистемыКонфигурацииПереопределяемый": "Точка расширения списка подсистем конфигурации, видимых библиотеке", "ПоискИУдалениеДублей": "Поиск дублей элементов справочников и их замена на выбранный оригинал", "ПоискИУдалениеДублейКлиент": "Клиентская часть поиска дублей", "ПоискИУдалениеДублейПереопределяемый": "Точка расширения поиска дублей: свои правила сравнения", "ПолнотекстовыйПоискКлиент": "Клиентская часть полнотекстового поиска", "ПолнотекстовыйПоискСервер": "Полнотекстовый поиск по данным: обновление индекса и выполнение поиска", "ПолнотекстовыйПоискСерверПереопределяемый": "Точка расширения полнотекстового поиска", "ПолучениеФайловИзИнтернета": "Загрузка файлов по HTTP и FTP: прокси, таймауты, проверка доступности ресурса", "ПолучениеФайловИзИнтернетаКлиент": "Клиентская часть загрузки файлов из интернета", "ПолучениеФайловИзИнтернетаКлиентСервер": "Общие для клиента и сервера параметры загрузки файлов из интернета", "ПолучениеФайловИзИнтернетаЛокализация": "Национальная специфика загрузки файлов из интернета", "Пользователи": "Пользователи программы и пользователи информационной базы: текущий пользователь, права и роли, полнота прав, служебные пользователи, связь элемента справочника с учетной записью ИБ", "ПользователиКлиент": "Клиентская часть работы с пользователями: сведения о текущем пользователе на клиенте", "ПользователиПереопределяемый": "Точка расширения подсистемы пользователей: свои роли, свои действия при создании и изменении пользователя", "ПрефиксацияОбъектовКлиентСервер": "Разбор и сборка номеров с префиксом на клиенте и сервере", "ПрефиксацияОбъектовКлиентСерверПереопределяемый": "Точка расширения префиксации: свои правила формирования номера", "ПрефиксацияОбъектовПереопределяемый": "Точка расширения префиксации: свои правила формирования префикса", "ПрефиксацияОбъектовСобытия": "Обработчики подписок на события, подставляющие префикс в номер или код объекта при записи", "ПроверкаЛегальностиПолученияОбновленияКлиент": "Клиентская часть проверки легальности получения обновления", "ПроверкаЛегальностиПолученияОбновленияПереопределяемый": "Точка расширения проверки легальности обновления", "РаботаВБезопасномРежиме": "Профили безопасности: запросы на использование внешних ресурсов - файлов, интернета, COM, внешних компонент, - и выполнение кода с этими разрешениями", "РаботаВБезопасномРежимеКлиент": "Клиентская часть профилей безопасности: интерактивное подтверждение запросов на внешние ресурсы", "РаботаВБезопасномРежимеКлиентПереопределяемый": "Клиентская точка расширения профилей безопасности", "РаботаВБезопасномРежимеПереопределяемый": "Точка расширения профилей безопасности: свои разрешения на внешние ресурсы", "РаботаВМоделиСервисаБСП": "Особенности работы библиотеки в модели сервиса: разделение данных и области", "РаботаСАдресами": "Разбор и сборка адресов: представление адреса, его поля, соответствие структуре адреса РФ", "РаботаСАдресамиКлиентСервер": "Общие для клиента и сервера правила работы со структурой адреса", "РаботаСБанками": "Классификатор банков: поиск по БИК и корсчету, загрузка классификатора", "РаботаСБанкамиКлиент": "Клиентская часть работы с классификатором банков", "РаботаСБанкамиПереопределяемый": "Точка расширения классификатора банков", "РаботаСКурсамиВалют": "Курсы валют: загрузка с сервиса, пересчет сумм, курс на дату", "РаботаСКурсамиВалютКлиентЛокализация": "Национальная специфика курсов валют на клиенте", "РаботаСКурсамиВалютКлиентСервер": "Пересчет сумм по курсу на клиенте и сервере", "РаботаСКурсамиВалютЛокализация": "Национальная специфика загрузки и применения курсов валют", "РаботаСКурсамиВалютПереопределяемый": "Точка расширения курсов валют: свой источник курсов", "РаботаСПочтовымиСообщениями": "Отправка и получение электронной почты: учетные записи, отправка писем, загрузка входящих", "РаботаСПочтовымиСообщениямиКлиент": "Клиентская часть работы с почтой: формы отправки писем", "РаботаСПочтовымиСообщениямиКлиентПереопределяемый": "Клиентская точка расширения работы с почтой", "РаботаСПочтовымиСообщениямиЛокализация": "Национальная специфика работы с почтой", "РаботаСПочтовымиСообщениямиПереопределяемый": "Точка расширения работы с почтой", "РаботаСФайлами": "Присоединенные файлы объектов: создание, чтение, изменение и версии файлов, хранение в базе или на диске, блокировка на редактирование", "РаботаСФайламиКлиент": "Клиентская часть работы с присоединенными файлами: команды открытия и редактирования, сканирование, обмен файлами с рабочим местом", "РаботаСФайламиКлиентПереопределяемый": "Клиентская точка расширения работы с присоединенными файлами", "РаботаСФайламиКлиентСервер": "Общие для клиента и сервера правила работы с присоединенными файлами: разбор имен, проверка расширений, параметры сканирования", "РаботаСФайламиЛокализация": "Национальная специфика работы с присоединенными файлами", "РаботаСФайламиПереопределяемый": "Точка расширения присоединенных файлов: свои правила хранения и обработки файлов объектов", "РассылкаОтчетов": "Рассылка отчетов по расписанию: состав рассылки, получатели, формирование и отправка", "РассылкаОтчетовКлиентПереопределяемый": "Клиентская точка расширения рассылки отчетов", "РассылкаОтчетовПереопределяемый": "Точка расширения рассылки отчетов", "РегистрСведений.НеудаленныеОбъекты (модуль менеджера)": "Объекты, которые не удалось удалить из-за ссылок на них", "РегистрСведений.СнимкиОтчетов (модуль менеджера)": "Хранение и чтение сохраненных результатов отчетов", "РегламентированныеДанныеКлиентСервер": "Общие правила работы с регламентированными сведениями на клиенте и сервере", "РегламентныеЗаданияПереопределяемый": "Точка расширения регламентных заданий: свои задания и их расписания", "РегламентныеЗаданияСервер": "Регламентные и фоновые задания: расписание, включение и выключение, выполнение с учетом модели сервиса", "РезервноеКопированиеИБКлиент": "Клиентская часть резервного копирования информационной базы", "РезервноеКопированиеИБКлиентПереопределяемый": "Клиентская точка расширения резервного копирования", "СерверныеОповещения": "Оповещения, инициированные сервером и доставляемые на открытые сеансы пользователей", "СерверныеОповещенияКлиент": "Прием серверных оповещений на клиенте и реакция на них", "СервисКриптографииDSSПереопределяемый": "Точка расширения сервиса криптографии DSS", "СервисМобильнойПодписи": "Подписание документов через сервис мобильной подписи", "СервисМобильнойПодписиКлиент": "Клиентская часть сервиса мобильной подписи", "СервисМобильнойПодписиКлиентСервер": "Общие правила работы с сервисом мобильной подписи", "СервисМобильнойПодписиПереопределяемый": "Точка расширения сервиса мобильной подписи", "СклонениеПредставленийОбъектов": "Склонение наименований и ФИО по падежам на сервере", "СклонениеПредставленийОбъектовКлиент": "Клиентская часть склонения представлений", "СклонениеПредставленийОбъектовКлиентСервер": "Общие правила склонения на клиенте и сервере", "СнимкиОтчетов": "Сохраненные результаты отчетов и работа с ними", "СоединенияИБ": "Завершение работы пользователей: блокировка новых сеансов, отключение активных соединений", "СоединенияИБКлиент": "Клиентская часть завершения работы пользователей: предупреждение о скором отключении", "СоединенияИБПереопределяемый": "Точка расширения завершения работы пользователей", "СозданиеНаОсновании": "Команды создания объектов на основании других объектов", "СозданиеНаОснованииПереопределяемый": "Точка расширения создания на основании: свои команды ввода на основании", "СообщенияАдминистрированиеОбменаДаннымиКонтрольИнтерфейс": "Программный интерфейс сообщений контроля администрирования обмена в модели сервиса", "СообщенияАдминистрированиеОбменаДаннымиКонтрольОбработчикСообщения_2_1_2_1": "Обработчик сообщений контроля администрирования обмена, версия протокола 2.1.2.1", "СообщенияАдминистрированиеОбменаДаннымиУправлениеИнтерфейс": "Программный интерфейс сообщений управления администрированием обмена в модели сервиса", "СообщенияАдминистрированиеОбменаДаннымиУправлениеОбработчикСообщения_2_1_2_1": "Обработчик сообщений управления администрированием обмена, версия протокола 2.1.2.1", "СообщенияАдминистрированиеОбменаДаннымиУправлениеОбработчикСообщения_3_0_1_1": "Обработчик сообщений управления администрированием обмена, версия протокола 3.0.1.1", "СообщенияАдминистрированиеОбменаДаннымиУправлениеТрансляция_2_1_2_1": "Трансляция сообщений управления администрированием обмена между версиями протокола", "СообщенияКонтрольДополнительныхОтчетовИОбработокОбработчикТрансляции_1_0_0_1": "Трансляция сообщений контроля дополнительных отчетов и обработок между версиями протокола", "СообщенияОбменаДаннымиКонтрольИнтерфейс": "Программный интерфейс сообщений контроля обмена данными в модели сервиса", "СообщенияОбменаДаннымиКонтрольОбработчикСообщения_2_1_2_1": "Обработчик сообщений контроля обмена данными, версия протокола 2.1.2.1", "СообщенияОбменаДаннымиОбработчикСообщения": "Обработчик входящих сообщений обмена данными в модели сервиса", "СообщенияОбменаДаннымиУправлениеИнтерфейс": "Программный интерфейс сообщений управления обменом данными в модели сервиса", "СообщенияОбменаДаннымиУправлениеОбработчикСообщения_2_1_2_1": "Обработчик сообщений управления обменом данными, версия протокола 2.1.2.1", "СообщенияОбменаДаннымиУправлениеОбработчикСообщения_3_0_1_1": "Обработчик сообщений управления обменом данными, версия протокола 3.0.1.1", "СообщенияОбменаДаннымиУправлениеОбработчикТрансляции_2_1_2_1": "Трансляция сообщений управления обменом между версиями протокола", "СообщенияУправленияДОИООбработчикСообщения_1_0_1_1": "Обработчик сообщений управления дополнительными отчетами и обработками, версия протокола 1.0.1.1", "СообщенияУправленияДОИООбработчикСообщения_1_0_1_2": "Обработчик сообщений управления дополнительными отчетами и обработками, версия протокола 1.0.1.2", "СообщенияУправленияДополнительнымиОтчетамиИОбработкамиИнтерфейс": "Программный интерфейс сообщений управления дополнительными отчетами и обработками в модели сервиса", "СтандартныеПодсистемыКлиент": "Обработка событий приложения на клиенте: старт, завершение, обработка ошибок, действия при открытии форм", "СтандартныеПодсистемыКлиентСервер": "Общие для клиента и сервера параметры встраивания библиотеки", "СтандартныеПодсистемыКлиентСерверЛокализация": "Национальная специфика служебного слоя, общая для клиента и сервера", "СтандартныеПодсистемыСервер": "Служебный слой встраивания библиотеки: обработка событий приложения на сервере, параметры работы программы, поддержка форм", "СтандартныеПодсистемыСерверЛокализация": "Национальная специфика служебного слоя библиотеки на сервере", "СтроковыеФункции": "Серверные операции над строками, которым нужен доступ к базе", "СтроковыеФункцииКлиент": "Клиентские операции над строками", "СтроковыеФункцииКлиентСервер": "Разбор и сборка строк без обращения к базе: разделение и склейка, форматированные строки, числа прописью, извлечение текста из HTML, сравнение версий", "СтроковыеФункцииКлиентСерверЛокализация": "Национальная специфика строковых функций", "СтроковыеФункцииКлиентСерверРФ": "Строковые функции, специфичные для РФ", "СтруктураПодчиненностиПереопределяемый": "Точка расширения отчета о структуре подчиненности документов", "ТекущиеДелаКлиент": "Клиентская часть текущих дел: переход по делу", "ТекущиеДелаПереопределяемый": "Точка расширения текущих дел: свои дела на начальной странице", "ТекущиеДелаСервер": "Начальная страница с текущими делами: состав дел, счетчики, обновление", "ТранспортСообщенийОбмена": "Доставка сообщений обмена: файл, каталог, почта, FTP, веб-сервис и прочие способы передачи", "ТранспортСообщенийОбменаПереопределяемый": "Точка расширения транспорта сообщений: свой способ доставки", "УдалениеПомеченныхОбъектов": "Удаление помеченных на удаление объектов с контролем ссылочной целостности", "УдалениеПомеченныхОбъектовКлиент": "Клиентская часть удаления помеченных объектов", "УдалениеПомеченныхОбъектовПереопределяемый": "Точка расширения удаления помеченных объектов", "УправлениеДоступом": "Ограничение доступа на уровне записей и полей: группы доступа, профили, значения и наборы значений доступа, включение и выключение ограничений, настройка форм под права", "УправлениеДоступомПереопределяемый": "Точка расширения управления доступом: свои виды доступа, свои наборы значений доступа для объектов конфигурации", "УправлениеКолонтитулами": "Колонтитулы печатных форм и отчетов", "УправлениеКонтактнойИнформацией": "Адреса, телефоны, почта и прочая контактная информация объектов: чтение и запись, виды контактной информации, проверка и разбор адресов, классификатор стран мира", "УправлениеКонтактнойИнформациейКлиент": "Клиентская часть контактной информации: ввод и редактирование на форме, команды перехода по адресу и почте", "УправлениеКонтактнойИнформациейКлиентЛокализация": "Национальная специфика контактной информации на клиенте", "УправлениеКонтактнойИнформациейКлиентСервер": "Общие для клиента и сервера правила разбора и представления контактной информации", "УправлениеКонтактнойИнформациейКлиентСерверЛокализация": "Национальная специфика контактной информации, общая для клиента и сервера", "УправлениеКонтактнойИнформациейЛокализация": "Национальная специфика контактной информации на сервере", "УправлениеКонтактнойИнформациейПереопределяемый": "Точка расширения контактной информации: свои виды контактной информации и правила их обработки", "УправлениеПечатью": "Печать документов: формирование печатных форм, их состав и параметры, макеты в форматах офисных документов, отправка на принтер и сохранение", "УправлениеПечатьюКлиент": "Клиентская часть печати: выполнение команд печати, предварительный просмотр, работа с офисными документами на стороне клиента", "УправлениеПечатьюКлиентПереопределяемый": "Клиентская точка расширения печати: свои действия при выполнении команд печати", "УправлениеПечатьюМультиязычностьПереопределяемый": "Точка расширения многоязычности печатных форм", "УправлениеПечатьюПереопределяемый": "Точка расширения печати: свои печатные формы, свои команды печати, подмена макетов", "УправлениеПечатьюРФ": "Печатные формы, специфичные для РФ", "УправлениеСвойствами": "Дополнительные реквизиты и сведения: наборы свойств объекта, чтение и запись значений, вывод на форму", "УправлениеСвойствамиКлиент": "Клиентская часть дополнительных реквизитов и сведений: правка значений на форме", "УправлениеСвойствамиПереопределяемый": "Точка расширения дополнительных свойств: свои наборы свойств для объектов", "УчетОригиналовПервичныхДокументов": "Состояния оригиналов первичных документов: получен, подписан, отправлен, и отражение состояний в списках", "УчетОригиналовПервичныхДокументовКлиент": "Клиентская часть учета оригиналов: команды смены состояния на форме", "УчетОригиналовПервичныхДокументовКлиентПереопределяемый": "Клиентская точка расширения учета оригиналов первичных документов", "УчетОригиналовПервичныхДокументовПереопределяемый": "Точка расширения учета оригиналов первичных документов", "ФайловаяСистема": "Файлы и каталоги на стороне сервера: временные файлы, каталоги, безопасное создание и удаление", "ФайловаяСистемаКлиент": "Файлы на рабочем месте пользователя: выбор, загрузка и сохранение файлов, запуск внешних приложений, работа с временным хранилищем", "ФизическиеЛицаКлиентСервер": "Разбор и сборка ФИО физических лиц на клиенте и сервере", "ФизическиеЛицаКлиентСерверЛокализация": "Национальная специфика работы с ФИО", "ЦентрМониторинга": "Отправка обезличенной статистики использования программы в центр мониторинга 1С", "ЦентрМониторингаКлиент": "Клиентская часть центра мониторинга: запрос согласия пользователя", "ЦентрМониторингаПереопределяемый": "Точка расширения центра мониторинга: свои показатели", "ШаблоныСообщений": "Шаблоны писем и сообщений: подстановка данных объекта в текст, формирование сообщения по шаблону, вложения", "ШаблоныСообщенийКлиент": "Клиентская часть шаблонов сообщений: выбор шаблона и правка сообщения", "ШаблоныСообщенийКлиентСервер": "Общие правила разбора шаблонов сообщений", "ШаблоныСообщенийПереопределяемый": "Точка расширения шаблонов сообщений: свои источники данных для подстановки", "ШаблоныСообщенийСервер": "Серверные операции над шаблонами сообщений", "ЭлектроннаяПодпись": "Электронная подпись и шифрование на сервере: подписание данных, проверка подписи, сертификаты и их свойства, криптопровайдеры", "ЭлектроннаяПодписьКлиент": "Клиентская часть электронной подписи: интерактивное подписание и проверка, добавление сертификата, установка расширения криптографии", "ЭлектроннаяПодписьКлиентЛокализация": "Национальная специфика электронной подписи на клиенте", "ЭлектроннаяПодписьКлиентПереопределяемый": "Клиентская точка расширения электронной подписи", "ЭлектроннаяПодписьКлиентСервер": "Общие для клиента и сервера правила работы с -
subsystem-map.md 22.5 KB
# Карта подсистем БСП Собрано генератором из версий: 3.1.11, 3.2.1. Правка вручную бессмысленна - файл перезаписывается при пересборке справочника. Имя подсистемы в документации и имя модуля в коде совпадают не всегда: механизм печати живет в `УправлениеПечатью`, свойства - в `УправлениеСвойствами`, а базовая функциональность - в `ОбщегоНазначения`. Поэтому модуль ищется по этой таблице, а не по названию подсистемы. Цифра в скобках - сколько методов подсистемы объявлено в этом модуле. | Подсистема | Программный интерфейс | Точки расширения | |---|---|---| | Базовая функциональность | `ОбщегоНазначения` (192), `ОбщегоНазначенияКлиентСервер` (83), `ОбщегоНазначенияКлиент` (54), `АдминистрированиеКластера` (45), `СтандартныеПодсистемыКлиент` (27), `СтроковыеФункцииКлиентСервер` (23), `ФайловаяСистемаКлиент` (19), `СтандартныеПодсистемыСервер` (18), `РегламентныеЗаданияСервер` (16), `ДлительныеОперации` (13), и еще 19 | `ОбщегоНазначенияПереопределяемый` (21), `ОбщегоНазначенияКлиентПереопределяемый` (12), `МультиязычностьПереопределяемый` (1), `ПодсистемыКонфигурацииПереопределяемый` (1) | | Обмен данными | `Обработка.УниверсальныйОбменДаннымиXML (модуль объекта)` (50), `ОбменДаннымиСервер` (43), `ОбменДаннымиXDTOСервер` (33), `Обработка.КонвертацияОбъектовИнформационныхБаз (модуль объекта)` (17), `ОбменДаннымиКлиент` (15), `ОбменДаннымиСобытия` (15), `Обработка.РегистрацияИзмененийДляОбменаДанными (модуль объекта)` (5), `ОбменДаннымиВнешнееСоединение` (3), `ОбменДаннымиВызовСервера` (1), `Обработка.КонвертацияОбъектовXDTO (модуль объекта)` (1) | `ОбменДаннымиПереопределяемый` (14) | | Электронная подпись | `ЭлектроннаяПодписьКлиентЛокализация` (43), `ЭлектроннаяПодписьКлиент` (38), `ЭлектроннаяПодпись` (32), `ЭлектроннаяПодписьЛокализация` (31), `ЭлектроннаяПодписьКлиентСерверЛокализация` (22), `ЭлектроннаяПодписьКлиентСервер` (5) | `ЭлектроннаяПодписьПереопределяемый` (6), `ЗаявлениеНаСертификатПереопределяемый` (4), `ЭлектроннаяПодписьКлиентПереопределяемый` (4) | | Контактная информация | `УправлениеКонтактнойИнформацией` (66), `УправлениеКонтактнойИнформациейКлиент` (26), `УправлениеКонтактнойИнформациейЛокализация` (15), `РаботаСАдресами` (10), `УправлениеКонтактнойИнформациейКлиентСервер` (6), `УправлениеКонтактнойИнформациейКлиентЛокализация` (3), `РаботаСАдресамиКлиентСервер` (2), `УправлениеКонтактнойИнформациейКлиентСерверЛокализация` (1) | `УправлениеКонтактнойИнформациейПереопределяемый` (5) | | Обмен данными в модели сервиса | `СообщенияОбменаДаннымиКонтрольИнтерфейс` (17), `СообщенияАдминистрированиеОбменаДаннымиУправлениеИнтерфейс` (15), `ОбменДаннымиВМоделиСервиса` (14), `СообщенияАдминистрированиеОбменаДаннымиКонтрольИнтерфейс` (14), `СообщенияОбменаДаннымиУправлениеИнтерфейс` (11), `СообщенияАдминистрированиеОбменаДаннымиУправлениеТрансляция_2_1_2_1` (6), `СообщенияОбменаДаннымиУправлениеОбработчикТрансляции_2_1_2_1` (6), `АвтономнаяРабота` (5), `СообщенияАдминистрированиеОбменаДаннымиКонтрольОбработчикСообщения_2_1_2_1` (4), `СообщенияАдминистрированиеОбменаДаннымиУправлениеОбработчикСообщения_2_1_2_1` (4), и еще 5 | `ОбменДаннымиВМоделиСервисаПереопределяемый` (2) | | Обновление версии ИБ | `ОбновлениеИнформационнойБазы` (72) | `ОбновлениеИнформационнойБазыПереопределяемый` (13), `ОбновлениеИнформационнойБазыКлиентПереопределяемый` (2) | | Работа с файлами | `РаботаСФайламиКлиент` (39), `РаботаСФайлами` (29), `РаботаСФайламиКлиентСервер` (4), `РаботаСФайламиЛокализация` (2) | `РаботаСФайламиПереопределяемый` (11), `РаботаСФайламиКлиентПереопределяемый` (2) | | Печать | `УправлениеПечатью` (36), `УправлениеПечатьюКлиент` (12), `УправлениеПечатьюРФ` (1) | `УправлениеПечатьюПереопределяемый` (16), `УправлениеПечатьюКлиентПереопределяемый` (4), `УправлениеПечатьюМультиязычностьПереопределяемый` (1) | | Бизнес-процессы и задачи | `БизнесПроцессыИЗадачиСервер` (36), `БизнесПроцессыИЗадачиКлиент` (19), `БизнесПроцессыИЗадачиКлиентСервер` (2) | `БизнесПроцессыИЗадачиПереопределяемый` (10), `БизнесПроцессыИЗадачиКлиентПереопределяемый` (1) | | Пользователи | `Пользователи` (41), `ВнешниеПользователи` (7), `ПользователиКлиент` (4), `ВнешниеПользователиКлиент` (1) | `ПользователиПереопределяемый` (11) | | Варианты отчетов | `ВариантыОтчетов` (15), `ОтчетыСервер` (7), `СнимкиОтчетов` (5), `ВариантыОтчетовКлиент` (3), `РегистрСведений.СнимкиОтчетов (модуль менеджера)` (3), `ВариантыОтчетовКлиентСервер` (1), `ОтчетыКлиент` (1), `ОтчетыКлиентСервер` (1), `УправлениеКолонтитулами` (1) | `ОтчетыКлиентПереопределяемый` (9), `ВариантыОтчетовПереопределяемый` (6), `ОтчетыПереопределяемый` (4) | | Управление доступом | `УправлениеДоступом` (40) | `УправлениеДоступомПереопределяемый` (11) | | Свойства | `УправлениеСвойствами` (36), `УправлениеСвойствамиКлиент` (6) | `УправлениеСвойствамиПереопределяемый` (6) | | Шаблоны сообщений | `ШаблоныСообщений` (20), `ШаблоныСообщенийКлиент` (4), `ШаблоныСообщенийКлиентСервер` (4), `ШаблоныСообщенийСервер` (1) | `ШаблоныСообщенийПереопределяемый` (8) | | Транспорт сообщений обмена | `ТранспортСообщенийОбмена` (24), `ИнтеграцияПодсистемБСП` (1), `Обработка.ТранспортСообщенийОбменаESB1C (модуль менеджера)` (1), `УправлениеПечатью` (1) | `ТранспортСообщенийОбменаПереопределяемый` (5) | | Учет оригиналов первичных документов | `УчетОригиналовПервичныхДокументов` (17), `УчетОригиналовПервичныхДокументовКлиент` (12) | `УчетОригиналовПервичныхДокументовПереопределяемый` (6), `УчетОригиналовПервичныхДокументовКлиентПереопределяемый` (2) | | Организации | `ОрганизацииСервер` (18) | `ОрганизацииПереопределяемый` (16) | | Дополнительные отчеты и обработки | `ДополнительныеОтчетыИОбработкиКлиентСервер` (16), `ДополнительныеОтчетыИОбработки` (10), `ДополнительныеОтчетыИОбработкиКлиент` (4) | `ДополнительныеОтчетыИОбработкиПереопределяемый` (2), `ДополнительныеОтчетыИОбработкиКлиентПереопределяемый` (1) | | Контроль ведения учета | `КонтрольВеденияУчета` (22), `КонтрольВеденияУчетаКлиент` (3) | `КонтрольВеденияУчетаПереопределяемый` (5) | | Машиночитаемые доверенности | `МашиночитаемыеДоверенностиФНС` (9), `МашиночитаемыеДоверенностиФНСКлиент` (5) | `МашиночитаемыеДоверенностиФНСПереопределяемый` (9), `МашиночитаемыеДоверенностиФНСКлиентПереопределяемый` (7) | | Защита персональных данных | `ЗащитаПерсональныхДанных` (15), `ЗащитаПерсональныхДанныхКлиент` (4) | `ЗащитаПерсональныхДанныхПереопределяемый` (10) | | Работа с почтовыми сообщениями | `РаботаСПочтовымиСообщениями` (16), `РаботаСПочтовымиСообщениямиКлиент` (4), `РаботаСПочтовымиСообщениямиЛокализация` (4) | `РаботаСПочтовымиСообщениямиПереопределяемый` (4), `РаботаСПочтовымиСообщениямиКлиентПереопределяемый` (1) | | Взаимодействия | `Взаимодействия` (12), `ВзаимодействияКлиент` (7), `ВзаимодействияЛокализация` (3), `ВзаимодействияКлиентСервер` (1) | `ВзаимодействияПереопределяемый` (3), `ВзаимодействияКлиентСерверПереопределяемый` (2) | | Профили безопасности | `РаботаВБезопасномРежиме` (15), `РаботаВБезопасномРежимеКлиент` (3) | `РаботаВБезопасномРежимеПереопределяемый` (8), `РаботаВБезопасномРежимеКлиентПереопределяемый` (1) | | Дополнительные отчеты и обработки в модели сервиса | `СообщенияУправленияДополнительнымиОтчетамиИОбработкамиИнтерфейс` (12), `СообщенияКонтрольДополнительныхОтчетовИОбработокОбработчикТрансляции_1_0_0_1` (6), `СообщенияУправленияДОИООбработчикСообщения_1_0_1_1` (4), `СообщенияУправленияДОИООбработчикСообщения_1_0_1_2` (4) | - | | Конструктор формул | `КонструкторФормул` (14), `КонструкторФормулКлиент` (8) | - | | Валюты | `РаботаСКурсамиВалютЛокализация` (10), `РаботаСКурсамиВалют` (6), `РаботаСКурсамиВалютКлиентЛокализация` (1), `РаботаСКурсамиВалютКлиентСервер` (1) | `РаботаСКурсамиВалютПереопределяемый` (2) | | Даты запрета изменения | `ДатыЗапретаИзменения` (15) | `ДатыЗапретаИзмененияПереопределяемый` (6) | | Напоминания пользователя | `НапоминанияПользователя` (9), `НапоминанияПользователяКлиент` (9), `НапоминанияПользователяКлиентСервер` (1) | `НапоминанияПользователяПереопределяемый` (2) | | Подключаемые команды | `ПодключаемыеКоманды` (5), `ПодключаемыеКомандыКлиент` (5), `ПодключаемыеКомандыКлиентСервер` (1), `СозданиеНаОсновании` (1) | `СозданиеНаОснованииПереопределяемый` (4), `ПодключаемыеКомандыПереопределяемый` (3), `ЗаполнениеОбъектовПереопределяемый` (2) | | Версионирование объектов | `ВерсионированиеОбъектов` (7), `ВерсионированиеОбъектовКлиент` (5), `ВерсионированиеОбъектовСобытия` (2) | `ВерсионированиеОбъектовПереопределяемый` (6) | | Оценка производительности | `ОценкаПроизводительностиКлиент` (11), `ОценкаПроизводительности` (9) | - | | Префиксация объектов | `ПрефиксацияОбъектовСобытия` (10), `ПрефиксацияОбъектовКлиентСервер` (5) | `ПрефиксацияОбъектовПереопределяемый` (3), `ПрефиксацияОбъектовКлиентСерверПереопределяемый` (1) | | Рассылка отчетов | `РассылкаОтчетов` (8) | `РассылкаОтчетовПереопределяемый` (8), `РассылкаОтчетовКлиентПереопределяемый` (3) | | Удаление помеченных объектов | `УдалениеПомеченныхОбъектов` (7), `УдалениеПомеченныхОбъектовКлиент` (7), `РегистрСведений.НеудаленныеОбъекты (модуль менеджера)` (2) | `УдалениеПомеченныхОбъектовПереопределяемый` (3) | | Обсуждения | `Обсуждения` (12), `ОбсужденияКлиент` (3), `ОбсужденияЛокализация` (2) | - | | Адресный классификатор | `АдресныйКлассификатор` (14), `АдресныйКлассификаторКлиент` (2) | - | | Календарные графики | `КалендарныеГрафики` (10), `КалендарныеГрафикиЛокализация` (1) | `КалендарныеГрафикиПереопределяемый` (4) | | Центр мониторинга | `ЦентрМониторинга` (10), `ЦентрМониторингаКлиент` (3) | `ЦентрМониторингаПереопределяемый` (2) | | Внешние компоненты | `ВнешниеКомпонентыКлиент` (8), `ВнешниеКомпонентыСервер` (3), `ВнешниеКомпонентыКлиентЛокализация` (2) | - | | Сервис мобильной подписи | `СервисМобильнойПодписи` (6), `СервисМобильнойПодписиКлиент` (3), `СервисМобильнойПодписиКлиентСервер` (1) | `СервисМобильнойПодписиПереопределяемый` (3) | | Текущие дела | `ТекущиеДелаСервер` (7), `ТекущиеДелаКлиент` (1) | `ТекущиеДелаПереопределяемый` (5) | | Завершение работы пользователей | `СоединенияИБ` (8), `СоединенияИБКлиент` (3) | `СоединенияИБПереопределяемый` (1) | | Загрузка данных из файла | `ЗагрузкаДанныхИзФайла` (6), `ЗагрузкаДанныхИзФайлаКлиентСервер` (3), `ЗагрузкаДанныхИзФайлаКлиент` (2) | `ЗагрузкаДанныхИзФайлаПереопределяемый` (1) | | Отправка SMS | `ОтправкаSMS` (4), `ОтправкаSMSКлиент` (2) | `ОтправкаSMSПереопределяемый` (4), `ОтправкаSMSКлиентПереопределяемый` (2) | | Поиск и удаление дублей | `ПоискИУдалениеДублей` (4), `ПоискИУдалениеДублейКлиент` (3) | `ПоискИУдалениеДублейПереопределяемый` (5) | | Получение файлов из Интернета | `ПолучениеФайловИзИнтернета` (7), `ПолучениеФайловИзИнтернетаКлиент` (2), `ПолучениеФайловИзИнтернетаЛокализация` (2), `ПолучениеФайловИзИнтернетаКлиентСервер` (1) | - | | Запрет редактирования реквизитов объектов | `ЗапретРедактированияРеквизитовОбъектовКлиент` (5), `ЗапретРедактированияРеквизитовОбъектов` (3) | `ЗапретРедактированияРеквизитовОбъектовПереопределяемый` (2) | | Склонение представлений объектов | `СклонениеПредставленийОбъектов` (7), `СклонениеПредставленийОбъектовКлиент` (2), `СклонениеПредставленийОбъектовКлиентСервер` (1) | - | | Настройки программы | - | `НастройкиПрограммыПереопределяемый` (8) | | Полнотекстовый поиск | `ПолнотекстовыйПоискСервер` (4), `ПолнотекстовыйПоискКлиент` (3) | `ПолнотекстовыйПоискСерверПереопределяемый` (1) | | Банки | `РаботаСБанками` (2), `РаботаСБанкамиКлиент` (1) | `РаботаСБанкамиПереопределяемый` (3) | | Графики работы | `ГрафикиРаботы` (6) | - | | Перевод текста | `ПереводТекстаНаДругиеЯзыки` (4), `ПереводТекстаНаДругиеЯзыкиЛокализация` (1) | - | | Групповое изменение объектов | `ГрупповоеИзменениеОбъектовКлиент` (1) | `ГрупповоеИзменениеОбъектовПереопределяемый` (3) | | Контроль работы пользователей | `КонтрольРаботыПользователей` (4) | - | | Обновление конфигурации | `ОбновлениеКонфигурацииКлиент` (3), `ОбновлениеКонфигурации` (1) | - | | Регламентные задания | - | `БлокировкаРаботыСВнешнимиРесурсамиПереопределяемый` (2), `РегламентныеЗаданияПереопределяемый` (2) | | Электронная подпись сервиса DSS | - | `СервисКриптографииDSSПереопределяемый` (4) | | Генерация штрихкода | `ГенерацияШтрихкода` (2), `УправлениеПечатью` (1) | - | | Настройка порядка элементов | `НастройкаПорядкаЭлементов` (3) | - | | Отчет о движениях документа | - | `ОтчетОДвиженияхДокументаПереопределяемый` (3) | | Регистрация | `ОбменДаннымиРегистрацияСервер` (3) | - | | Структура подчиненности | - | `СтруктураПодчиненностиПереопределяемый` (3) | | Базовая функциональность в модели сервиса | `РаботаВМоделиСервисаБСП` (2) | - | | Заметки пользователя | `ЗаметкиПользователя` (2) | - | | Проверка легальности получения обновления | `ПроверкаЛегальностиПолученияОбновленияКлиент` (1) | `ПроверкаЛегальностиПолученияОбновленияПереопределяемый` (1) | | Резервное копирование ИБ | `РезервноеКопированиеИБКлиент` (1) | `РезервноеКопированиеИБКлиентПереопределяемый` (1) | | Выгрузка объектов в файлы | `ВыгрузкаОбъектовВФайлы` (1) | - | | Интерфейс OData | - | `ИнтерфейсODataПереопределяемый` (1) | | Информация при запуске | - | `ИнформацияПриЗапускеПереопределяемый` (1) |
-
-
scripts
-
bsp-api.py 16 KB
#!/usr/bin/env python # -*- coding: utf-8 -*- """Поиск по справочнику API БСП. Справочник больше мегабайта и в контекст целиком не грузится - он спрашивается по месту. bsp-api.py find <текст> поиск по имени метода, модулю, подсистеме, механизму bsp-api.py show <Модуль.Метод> полная карточка метода bsp-api.py show <Метод> все методы с таким именем, в каких модулях bsp-api.py module <Модуль> состав модуля bsp-api.py modules [<текст>] перечень модулей bsp-api.py subsystem <текст> модули и механизмы подсистемы bsp-api.py overrides <текст> переопределяемые обработчики bsp-api.py check <Модуль.Метод> существует ли такой вызов; код возврата 1, если нет Отборы: --av S|T|F|E|C (контекст), --sub <подсистема>, --version <версия>, --limit N. """ import argparse import io import json import os import re import sys AV_LONG = {'S': 'Сервер', 'C': 'Вызов сервера', 'T': 'Тонкий клиент', 'F': 'Толстый клиент', 'E': 'Внешнее соединение'} SRC_LONG = { 'L': 'модуль назван в документации', 'P': 'модуль из примера вызова, подтвержден реализацией', 'PA': 'модуль из примера вызова плюс контексты выполнения', 'A': 'модуль выбран по контекстам выполнения', 'AP': 'контексты выполнения плюс пример вызова', 'O': 'модуль объекта или менеджера', 'OS': 'модуль объекта, выбран по подсистеме', 'P?': 'модуль назван в примере, но в дистрибутиве этой версии такого метода нет', '?': 'модуль не определен однозначно', } DB = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'references', 'bsp-api.jsonl') def read_reference(path): if not os.path.exists(path): raise SystemExit('справочник не найден: %s\nсобрать: scripts/bsp-build.py --help' % path) with io.open(path, encoding='utf-8') as fh: header = json.loads(fh.readline()) return header, [json.loads(line) for line in fh if line.strip()] def av_text(code): return ', '.join(AV_LONG.get(c, c) for c in code) or 'не указана' def matches(rec, words): """Совпадение по ВСЕМ словам запроса, а не по непрерывной подстроке. Запрос обычно описывает задачу ("реквизит объекта", "фоновое задание"), а слова из него в записи разнесены по имени, механизму и формулировке назначения. Поиск подстроки целиком такие запросы просто не находит. """ hay = ' '.join(filter(None, [rec['n'], rec['m'], rec.get('sub'), rec.get('grp'), rec.get('o'), rec.get('sig')])).lower() return all(w in hay for w in words) def keep(rec, args): if args.av and not all(c in rec.get('av', '') for c in args.av.upper()): return False if args.sub and args.sub.lower() not in (rec.get('sub') or '').lower(): return False if args.version and args.version not in rec.get('v', []): return False return True def line_of(rec): star = '' if rec['src'] in ('L', 'P', 'PA', 'O') else ' [?]' ver = ' [!]' if rec.get('was') else '' purpose = (' - ' + rec['o']) if rec.get('o') else '' return '%s.%s%s%s %s%s' % (rec['m'], rec['n'], star, ver, rec.get('av', ''), purpose) def card(rec, header): out = [] out.append('%s.%s' % (rec['m'], rec['n'])) if rec.get('o'): out.append(' %s' % rec['o']) out.append(' %s' % rec['sig']) out.append(' контексты: %s' % av_text(rec.get('av', ''))) if rec.get('p'): out.append(' параметры:') for p in rec['p']: bits = [p['n']] if p.get('t'): bits.append(p['t']) if p.get('d'): bits.append('по умолчанию ' + p['d']) if p.get('byval'): bits.append('Знач') out.append(' %s' % ' - '.join(bits)) if rec.get('ret'): out.append(' возвращает: %s' % rec['ret']) out.append(' подсистема: %s%s' % (rec['sub'], ', механизм ' + rec['grp'] if rec.get('grp') else '')) out.append(' раздел: %s' % ('переопределяемый обработчик' if rec['sec'] == 'П' else 'программный интерфейс')) out.append(' версии: %s' % ', '.join(rec.get('v', []))) for ver, delta in (rec.get('was') or {}).items(): bits = [] if delta.get('sig'): bits.append('сигнатура была: %s' % delta['sig']) if delta.get('k'): bits.append('была %s' % ('функцией' if delta['k'] == 'Ф' else 'процедурой')) if delta.get('ret'): bits.append('возвращала %s' % delta['ret']) if delta.get('av'): bits.append('контексты были: %s' % av_text(delta['av'])) if delta.get('sub'): bits.append('подсистема была: %s' % delta['sub']) out.append(' ВНИМАНИЕ, в %s иначе - %s' % (ver, '; '.join(bits))) mod = header['modules'].get(rec['m']) if mod: extra = ', повторное использование %s' % mod['reuse'] if mod.get('reuse') else '' out.append(' модуль: %s, методов %d%s' % (mod['kind'], mod.get('total', 0), extra)) if mod.get('o'): out.append(' назначение модуля: %s' % mod['o']) out.append(' источник: %s' % SRC_LONG.get(rec['src'], rec['src'])) return '\n'.join(out) def main(): # Вывод справочника - кириллица. Без явного переключения потока печать падает # с UnicodeEncodeError везде, где консоль не в UTF-8: сборочный агент, чужая локаль. sys.stdout.reconfigure(encoding='utf-8') sys.stderr.reconfigure(encoding='utf-8') ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) ap.add_argument('command', choices=['find', 'show', 'module', 'modules', 'subsystem', 'overrides', 'check', 'stats']) ap.add_argument('query', nargs='?', default='') ap.add_argument('--db', default=DB) ap.add_argument('--av', help='отбор по контексту: S сервер, T тонкий, F толстый, E внешнее, C вызов сервера') ap.add_argument('--sub', help='отбор по подсистеме') ap.add_argument('--version', help='отбор по версии БСП') ap.add_argument('--limit', type=int, default=40) args = ap.parse_args() header, recs = read_reference(args.db) q = args.query.strip() ql = q.lower() if args.command == 'stats': print('версии: %s' % ', '.join(header['versions'])) print('модулей: %d, методов: %d' % (len(header['modules']), len(recs))) subs = {} for r in recs: subs[r['sub']] = subs.get(r['sub'], 0) + 1 for k in sorted(subs, key=lambda x: -subs[x])[:20]: print(' %5d %s' % (subs[k], k)) return 0 if args.command == 'check': if '.' not in q: raise SystemExit('check ждет Модуль.Метод') mod, name = q.rsplit('.', 1) hit = [r for r in recs if r['m'].lower() == mod.lower() and r['n'].lower() == name.lower()] # Отбор по версии обязан действовать и здесь. Иначе на проекте с БСП 3.1.11 проверка # подтвердит метод, появившийся только в 3.2.1, - то есть сделает ровно обратное тому, # ради чего ее зовут. if hit and args.version: wrong = [r for r in hit if args.version not in r.get('v', [])] hit = [r for r in hit if args.version in r.get('v', [])] if not hit and wrong: print('%s - в версии %s НЕ СУЩЕСТВУЕТ; есть в: %s' % (q, args.version, ', '.join(sorted(set(v for r in wrong for v in r.get('v', [])))))) return 1 if hit: print('%s.%s - есть, %s' % (hit[0]['m'], hit[0]['n'], hit[0]['sig'])) # Существует - еще не значит "вызывай": устаревший метод по виду # не отличается от действующего. Код возврата не меняем, метод # существует; предупреждение читает человек либо валидатор. dep = hit[0].get('dep') if dep: print(' ВНИМАНИЕ: устаревший, вместо него %s' % dep) return 0 same = [r for r in recs if r['n'].lower() == name.lower()] print('%s - НЕ НАЙДЕН в справочнике БСП' % q) if same: print('метод с таким именем есть в: %s' % ', '.join(sorted({r['m'] for r in same}))) near = [r for r in recs if r['m'].lower() == mod.lower()] if near and not same: print('модуль есть, метода нет. Похожие имена в модуле: %s' % ', '.join(sorted(r['n'] for r in near if name.lower()[:5] in r['n'].lower())[:8])) elif not near: mods = sorted(m for m in header['modules'] if mod.lower()[:6] in m.lower()) if mods: print('модуля нет. Похожие: %s' % ', '.join(mods[:8])) return 1 if args.command == 'modules': rows = [(m, v) for m, v in header['modules'].items() if not q or ql in m.lower()] rows.sort(key=lambda x: -x[1].get('total', 0)) for m, v in rows[:args.limit]: print('%-52s %-4s методов %4d' % (m, v.get('av', ''), v.get('total', 0))) if v.get('o'): print(' %s' % v['o']) print('-- всего %d' % len(rows)) return 0 if args.command == 'module': rows = [r for r in recs if r['m'].lower() == ql] if not rows: # Частичное совпадение с НЕСКОЛЬКИМИ модулями склеивать нельзя: состав окажется # сборным, а шапка - от одного из них, и клиент-серверные методы припишутся клиенту. near = sorted({r['m'] for r in recs if ql in r['m'].lower()}) if len(near) > 1: print('уточните модуль, подходит %d: %s' % (len(near), ', '.join(near[:12]))) return 1 rows = [r for r in recs if ql in r['m'].lower()] if not rows: print('модуль не найден: %s' % q) return 1 rows = [r for r in rows if keep(r, args)] if not rows: print('модуль есть, но под отбор ничего не подходит') return 1 info = header['modules'].get(rows[0]['m'], {}) print('%s - %s, контексты: %s' % (rows[0]['m'], info.get('kind', ''), av_text(info.get('av', '')))) if info.get('o'): print(' %s' % info['o']) for r in sorted(rows, key=lambda x: x['n'])[:args.limit]: print(' %s %s' % ('Ф' if r['k'] == 'Ф' else 'П', r['sig'])) print('-- методов %d' % len(rows)) return 0 if args.command == 'subsystem': rows = [r for r in recs if (r.get('sub') or '').lower() == ql] if not rows: # "Обмен данными" подходит и к "Обмен данными в модели сервиса": склеив их, получим # чужие модули и счетчик от двух подсистем под именем одной. near = sorted({r['sub'] for r in recs if ql in (r.get('sub') or '').lower()}) if len(near) > 1: print('уточните подсистему, подходит %d: %s' % (len(near), '; '.join(near))) return 1 rows = [r for r in recs if ql in (r.get('sub') or '').lower()] if not rows: print('подсистема не найдена: %s' % q) return 1 rows = [r for r in rows if keep(r, args)] if not rows: print('подсистема есть, но под отбор ничего не подходит') return 1 mods, groups = {}, {} for r in rows: mods[r['m']] = mods.get(r['m'], 0) + 1 if r.get('grp'): groups[r['grp']] = groups.get(r['grp'], 0) + 1 print('подсистема: %s, методов %d' % (rows[0]['sub'], len(rows))) print('модули:') for m in sorted(mods, key=lambda x: -mods[x])[:args.limit]: print(' %-50s %4d' % (m, mods[m])) o = header['modules'].get(m, {}).get('o') if o: print(' %s' % o) if groups: print('механизмы:') for g in sorted(groups, key=lambda x: -groups[x])[:args.limit]: print(' %-50s %4d' % (g, groups[g])) return 0 if args.command == 'overrides': rows = [r for r in recs if r['sec'] == 'П' and (not q or matches(r, [w for w in ql.split() if w]))] rows = [r for r in rows if keep(r, args)] for r in sorted(rows, key=lambda x: (x['m'], x['n']))[:args.limit]: print(line_of(r)) print('-- всего %d' % len(rows)) return 0 if args.command == 'show': if '.' in q: mod, name = q.rsplit('.', 1) rows = [r for r in recs if r['m'].lower() == mod.lower() and r['n'].lower() == name.lower()] else: rows = [r for r in recs if r['n'].lower() == ql] rows = [r for r in rows if keep(r, args)] if not rows: print('не найдено: %s' % q) return 1 print('\n\n'.join(card(r, header) for r in rows[:args.limit])) return 0 words = [w for w in ql.split() if w] if not words: raise SystemExit('find ждет текст запроса') rows = [r for r in recs if matches(r, words) and keep(r, args)] # Сперва то, где запрос попал в само имя метода: имена в БСП говорящие, и точное попадание # почти всегда и есть искомое. rows.sort(key=lambda r: (0 if all(w in r['n'].lower() for w in words) else 1, len(r['n']), r['m'], r['n'])) for r in rows[:args.limit]: print(line_of(r)) if len(rows) > args.limit: print('-- показано %d из %d, уточните запрос или поднимите --limit' % (args.limit, len(rows))) else: print('-- всего %d' % len(rows)) return 0 if __name__ == '__main__': sys.exit(main()) -
bsp-build.py 34.3 KB
#!/usr/bin/env python # -*- coding: utf-8 -*- """Сборка справочника API БСП: документация ИТС плюс реальная реализация библиотеки. Документация знает, ЧТО делает метод, но не знает, в каком общем модуле он лежит: крошки статьи называют механизм, а не модуль. Реализация знает модули и сигнатуры, но не знает, какая часть кода вынесена в публичный интерфейс. Справочник получается на стыке. Вход: --docs <версия>=<каталог скрапа ИТС> можно указать несколько раз --lib <каталог, куда v8unpack развернул 1Cv8.cf> --out <файл .jsonl> Скрап и дистрибутив библиотеки лицензионные и в репозиторий не кладутся. На выходе - только факты: имена, сигнатуры, типы, контексты выполнения, принадлежность подсистеме и версиям. Распаковать дистрибутив: python -m v8unpack -E 1Cv8.cf <каталог> --temp <каталог-temp> """ import argparse import collections import io import json import os import re import sys IDENT = r'[A-Za-z_А-яЁё][A-Za-z0-9_А-яЁё]*' # --- разбор страниц документации ------------------------------------------------------------ SEC_RE = re.compile(r'^(Синтаксис|Параметры|Возвращаемое значение|Пример вызова|Пример реализации|' r'Доступность|Расположение)\s*\n+```\n(.*?)```', re.S | re.M) SIGN_RE = re.compile(r'^\s*(?:(Асинх|Async)\s+)?(Процедура|Функция|Procedure|Function)\s+(' + IDENT + r')\s*\(', re.S) LOC_RE = re.compile(r'^[ \t]*Общий модуль\s+(' + IDENT + r')', re.M) PARAM_TYPE_RE = re.compile(r'\s{0,6}(' + IDENT + r')\s+-\s+([^-\n]{1,60}?)\s*(?:-|$)') # --- разбор кода ---------------------------------------------------------------------------- # Литерал ИЛИ комментарий: что началось раньше, то и поглощает второе. Закрывающая кавычка # необязательна - незакрытый литерал гасит остаток файла. NOISE_RE = re.compile(r'"(?:[^"]|"")*"?|//[^\n]*') SIG_RE = re.compile(r'^[ \t]*(?:(Асинх|Async)[ \t]+)?(Процедура|Функция|Procedure|Function)[ \t]+(' + IDENT + r')[ \t]*\(', re.IGNORECASE | re.MULTILINE) TAIL_RE = re.compile(r'^\s*(Экспорт|Export)\b', re.IGNORECASE) # Позиции флагов в CommonModule.json (v8unpack), расшифрованы сверкой с XML-выгрузкой на 425 # модулях с полным совпадением. Шестая позиция - не флаг, а ReturnValuesReuse. FLAG_POS = {0: 'ClientOrdinaryApplication', 1: 'Server', 2: 'ExternalConnection', 3: 'Privileged', 4: 'Global', 5: 'ClientManagedApplication', 7: 'ServerCall'} REUSE = {'0': None, '1': 'НаВремяВызова', '2': 'НаВремяСеанса'} AV_SHORT = {'Сервер': 'S', 'Вызов сервера': 'C', 'Тонкий клиент': 'T', 'Толстый клиент': 'F', 'Внешнее соединение': 'E'} # Источник имени модуля. Показывает, насколько запись факт, а не вывод: L - документация назвала # модуль сама; P - префикс из примера, подтвержденный реализацией; A - выбор по контекстам # выполнения; O - модуль объекта или менеджера; P? - имя названо документацией, но в дистрибутиве # этой версии такого метода нет (объект выведен из поставки либо документация отстала). SRC_CODE = {'Расположение': 'L', 'префикс подтвержден реализацией': 'P', 'префикс плюс доступность': 'PA', 'доступность': 'A', 'доступность плюс префикс': 'AP', 'модуль объекта или менеджера': 'O', 'модуль объекта, выбран по подсистеме': 'OS', 'префикс без подтверждения': 'P?'} KIND_RU = { 'Catalog': 'Справочник', 'Document': 'Документ', 'DataProcessor': 'Обработка', 'Report': 'Отчет', 'InformationRegister': 'РегистрСведений', 'AccumulationRegister': 'РегистрНакопления', 'BusinessProcess': 'БизнесПроцесс', 'ChartOfCharacteristicType': 'ПланВидовХарактеристик', 'Task': 'Задача', 'ExchangePlan': 'ПланОбмена', 'Constant': 'Константа', 'DocumentJournal': 'ЖурналДокументов', 'WebService': 'WebСервис', 'HTTPService': 'HTTPСервис', 'FilterCriterion': 'КритерийОтбора', 'SettingsStorage': 'ХранилищеНастроек', 'CalculationRegister': 'РегистрРасчета', 'AccountingRegister': 'РегистрБухгалтерии', } # Префиксы из примеров вызова, которые общими модулями не являются. NOT_A_MODULE_RE = re.compile(r'(Объект|Ссылка|Менеджер|Форма|Набор|Запись)$') # Менеджер объектов метаданных в примерах: Обработки.Имя, Отчеты.Имя и так далее. MANAGER_RU = {'Обработки': 'Обработка', 'Отчеты': 'Отчет', 'Справочники': 'Справочник', 'Документы': 'Документ', 'РегистрыСведений': 'РегистрСведений', 'РегистрыНакопления': 'РегистрНакопления', 'ПланыОбмена': 'ПланОбмена', 'БизнесПроцессы': 'БизнесПроцесс', 'Задачи': 'Задача', 'ЖурналыДокументов': 'ЖурналДокументов', 'Константы': 'Константа'} # Пример вида "ОбработкаОбъект = Обработки.Имя.Создать();" - дальше метод зовут через переменную, # и без этой связки настоящее имя обработки теряется. CREATE_RE = re.compile(r'(' + IDENT + r')\s*=\s*(' + '|'.join(MANAGER_RU) + r')\.(' + IDENT + r')\s*\.\s*(?:Создать\w*)\s*\(') MANAGER_CALL_RE = re.compile(r'(' + '|'.join(MANAGER_RU) + r')\.(' + IDENT + r')\s*\.\s*%s\b') def blank_noise(text): """Гасит строковые литералы и комментарии за один проход, сохраняя длину и переводы строк.""" def blank(m): s = m.group(0) if s[0] == '/': return ' ' * len(s) closed = len(s) >= 2 and s[-1] == '"' inner = s[1:-1] if closed else s[1:] body = ' ' * len(inner) if '\n' not in inner \ else ''.join('\n' if c == '\n' else ' ' for c in inner) return '"' + body + ('"' if closed else '') return NOISE_RE.sub(blank, text) def exported_methods(text): """Экспортные методы модуля: имя, вид, сигнатура одной строкой.""" src = blank_noise(text) out = [] for m in SIG_RE.finditer(src): i, depth = m.end() - 1, 0 while i < len(src): if src[i] == '(': depth += 1 elif src[i] == ')': depth -= 1 if depth == 0: break i += 1 if depth != 0: continue if not TAIL_RE.match(src[i + 1:i + 240].lstrip('\r\n \t')): continue out.append({'name': m.group(3), 'kind': m.group(2), 'async': bool(m.group(1)), 'signature': ' '.join(text[m.start():i + 1].split())}) return out def read_module_text(path): if not os.path.exists(path): return '' return io.open(path, encoding='utf-8-sig', errors='replace', newline='').read() # --- сторона реализации --------------------------------------------------------------------- def parse_impl(root): """Контейнеры кода библиотеки: общие модули плюс модули объектов и менеджеров. Формы не берутся: их методы программным интерфейсом библиотеки не являются. """ containers = {} base = os.path.join(root, 'CommonModule') if not os.path.isdir(base): raise SystemExit('в каталоге %s нет папки CommonModule - это не распакованный .cf' % root) for name in sorted(os.listdir(base)): d = os.path.join(base, name) jp = os.path.join(d, 'CommonModule.json') if not os.path.isdir(d) or not os.path.exists(jp): continue meta = json.load(io.open(jp, encoding='utf-8')) flags, reuse = {}, None try: tail = meta['header'][0][1][2:10] if len(tail) >= 8 and all(isinstance(v, str) for v in tail): flags = {n: tail[p] == '1' for p, n in FLAG_POS.items()} reuse = REUSE.get(tail[6]) except (KeyError, IndexError, TypeError): pass av = [] for flag, label in (('Server', 'Сервер'), ('ServerCall', 'Вызов сервера'), ('ClientManagedApplication', 'Тонкий клиент'), ('ClientOrdinaryApplication', 'Толстый клиент'), ('ExternalConnection', 'Внешнее соединение')): if flags.get(flag): av.append(label) containers[name] = {'kind': 'ОбщийМодуль', 'availability': av, 'reuse': reuse, 'privileged': bool(flags.get('Privileged')), 'methods': exported_methods(read_module_text( os.path.join(d, 'CommonModule.obj.bsl')))} for kind in sorted(os.listdir(root)): kd = os.path.join(root, kind) if kind == 'CommonModule' or not os.path.isdir(kd): continue ru = KIND_RU.get(kind, kind) for obj in sorted(os.listdir(kd)): od = os.path.join(kd, obj) if not os.path.isdir(od): continue for suffix, label in ((kind + '.obj.bsl', 'модуль объекта'), (kind + '.mgr.bsl', 'модуль менеджера')): ms = exported_methods(read_module_text(os.path.join(od, suffix))) if not ms: continue containers['%s.%s (%s)' % (ru, obj, label)] = { 'kind': ru, 'availability': [], 'reuse': None, 'privileged': False, 'methods': ms} return containers # --- сторона документации ------------------------------------------------------------------- def split_params(sig): """Параметры из сигнатуры: имя, передача по значению, значение по умолчанию.""" i = sig.find('(') if i < 0: return [] depth, j = 0, i while j < len(sig): if sig[j] == '(': depth += 1 elif sig[j] == ')': depth -= 1 if depth == 0: break j += 1 # Запятая разделяет параметры только вне скобок И вне строкового литерала: у части методов # значение по умолчанию - это сама запятая, например Разделитель = ",". parts, depth, cur, in_str = [], 0, '', False for ch in sig[i + 1:j]: if in_str: cur += ch if ch == '"': in_str = False continue if ch == '"': in_str = True cur += ch continue if ch in '([': depth += 1 elif ch in ')]': depth -= 1 if ch == ',' and depth == 0: parts.append(cur) cur = '' else: cur += ch if cur.strip(): parts.append(cur) out = [] for p in parts: p = ' '.join(p.split()) if not p: continue byval = bool(re.match(r'(Знач|Val)\s+', p, re.I)) rest = re.sub(r'^(Знач|Val)\s+', '', p, flags=re.I) name, _, dflt = rest.partition('=') out.append({'name': name.strip(), 'byval': byval, 'default': dflt.strip() or None}) return out def parse_docs(root): """Страницы главы 4 - программного интерфейса.""" meta = json.load(io.open(os.path.join(root, '_meta.json'), encoding='utf-8')) out = [] for x in meta: b = x['breadcrumb'] if len(b) < 4 or not b[1].startswith('Глава 4'): continue p = os.path.join(root, 'markdown', x['filename_base'] + '.md') if not os.path.exists(p): continue body = io.open(p, encoding='utf-8').read() body = body.split('---', 2)[2] if body.startswith('---') else body secs = {m.group(1): m.group(2).strip('\n') for m in SEC_RE.finditer(body)} if 'Синтаксис' not in secs: continue ms = SIGN_RE.match(secs['Синтаксис'].strip()) if not ms: continue name = ms.group(3) module, source, cands = None, None, [] if 'Расположение' in secs: ml = LOC_RE.search(secs['Расположение']) if ml: module, source = ml.group(1), 'Расположение' if module is None: # Метод могут звать прямо через менеджер: Обработки.Имя.Метод(). mc = MANAGER_CALL_RE.pattern % re.escape(name) for mm in re.finditer(mc, body): cands.append('%s.%s (модуль менеджера)' % (MANAGER_RU[mm.group(1)], mm.group(2))) # Либо через переменную, которой присвоили Обработки.Имя.Создать(). created = {mm.group(1): '%s.%s (модуль объекта)' % (MANAGER_RU[mm.group(2)], mm.group(3)) for mm in CREATE_RE.finditer(body)} pref = collections.Counter( mm.group(1) for mm in re.finditer(r'(' + IDENT + r')\.' + re.escape(name) + r'\b', body)) for p in pref: if p in created: cands.append(created[p]) elif not NOT_A_MODULE_RE.search(p): cands.append(p) cands = sorted(set(cands)) types = {} for line in (secs.get('Параметры') or '').split('\n'): m = PARAM_TYPE_RE.match(line) if m: types.setdefault(m.group(1), m.group(2).strip()) params = split_params(' '.join(secs['Синтаксис'].split())) for pr in params: pr['type'] = types.get(pr['name']) out.append({ 'name': name, 'async': bool(ms.group(1)), 'kind': ms.group(2), 'subsystem': b[2], 'section': b[3], 'group': b[4] if len(b) > 5 else None, 'module': module, 'module_source': source, 'candidates': cands, 'availability': [s.strip() for s in secs.get('Доступность', '').split(',') if s.strip()], 'signature': ' '.join(secs['Синтаксис'].split()), 'params': params, 'returns': secs.get('Возвращаемое значение'), }) return out # --- сшивка --------------------------------------------------------------------------------- def public_only(cands, section): """Отсев кандидатов, которые публичным интерфейсом быть не могут. Оба правила проверены сплошь: ни один документированный метод не лежит в служебном модуле, а раздел Переопределение ложится ровно в переопределяемые модули и никуда больше. """ out = [c for c in cands if 'Служебн' not in c] if section == 'Переопределение': pick = [c for c in out if 'Переопределяем' in c] else: pick = [c for c in out if 'Переопределяем' not in c] return pick or out or list(cands) def resolve_module(doc, impl, by_name): """Модуль метода. Возвращает (модуль, источник) - источник показывает, насколько это факт.""" owners = by_name.get(doc['name'].lower(), []) common = public_only([c for c in owners if impl[c]['kind'] == 'ОбщийМодуль'], doc['section']) other = sorted(set(c for c in owners if impl[c]['kind'] != 'ОбщийМодуль')) av = set(doc['availability']) if doc['module_source'] == 'Расположение': m = doc['module'] return (m, 'Расположение') if m in impl else (m, 'Расположение (в реализации нет)') fixed = [] for c in doc['candidates']: if c in impl: fixed.append(c) elif c.startswith('Модуль') and c[6:] in impl: fixed.append(c[6:]) # идиома ОбщегоНазначения.ОбщийМодуль("Имя") confirmed = sorted(set(c for c in fixed if c in common)) if len(confirmed) == 1: return confirmed[0], 'префикс подтвержден реализацией' if len(confirmed) > 1: byav = [c for c in confirmed if set(impl[c]['availability']) == av] if len(byav) == 1: return byav[0], 'префикс плюс доступность' if common: byav = [c for c in sorted(set(common)) if set(impl[c]['availability']) == av] if len(byav) == 1: return byav[0], 'доступность' if len(byav) > 1: inter = [c for c in byav if c in fixed] if len(inter) == 1: return inter[0], 'доступность плюс префикс' return None, 'несколько общих модулей с одной доступностью' return None, 'доступность не совпала ни с одним общим модулем' if other: if len(other) == 1: return other[0], 'модуль объекта или менеджера' sub = re.sub(r'[^A-Za-zА-яЁё]', '', doc['subsystem']).lower()[:10] near = [c for c in other if sub and sub in re.sub(r'[^A-Za-zА-яЁё]', '', c).lower()] if len(near) == 1: return near[0], 'модуль объекта, выбран по подсистеме' return None, 'метод есть в %d модулях объектов' % len(other) if len(set(fixed)) == 1: return sorted(set(fixed))[0], 'префикс без подтверждения' # Последняя попытка: документация называет владельца, а в этой сборке библиотеки его нет. # Так бывает у обработок обмена, выведенных из поставки: имя из примера достоверно, а # проверить его нечем. Отдаем с явной пометкой, а не молчим. raw = sorted(set(c for c in doc['candidates'] if not NOT_A_MODULE_RE.search(c))) if len(raw) == 1: return raw[0], 'префикс без подтверждения' return None, 'метода нет в реализации' def version_deltas(by_ver, versions, base_rec): """Чем метод отличался в прежних версиях от того, что записано как основное. Записывать только последнюю версию нельзя: между 3.1.11 и 3.2.1 у части методов изменилась сигнатура, причем ломающе - процедура стала функцией, параметр вставлен НЕ в конец. Код, написанный по новой сигнатуре, на старой версии передаст аргументы не туда. """ if len(by_ver) < 2: return None newest = [v for v in versions if v in by_ver][-1] out = {} for ver in versions: if ver not in by_ver or ver == newest: continue d = by_ver[ver] delta = {} if d['signature'] != base_rec['sig']: delta['sig'] = d['signature'] av = ''.join(AV_SHORT.get(a, '?') for a in d['availability']) if av != base_rec['av']: delta['av'] = av # Отличие по возврату записывается только когда ОБА типа названы. Отсутствие секции в # старой документации - это ее неполнота, а не смена контракта, и в отличия не идет. rt = return_type(d.get('returns')) if rt and base_rec.get('ret') and rt != base_rec['ret']: delta['ret'] = rt kind = 'Ф' if d['kind'].lower().startswith(('функ', 'func')) else 'П' if kind != base_rec['k']: delta['k'] = kind if d['subsystem'] != base_rec['sub']: delta['sub'] = d['subsystem'] if delta: out[ver] = delta return out or None def return_type(raw): """Тип возвращаемого значения - первое слово секции.""" if not raw: return None m = re.match(r'\s*см\.\s*(' + IDENT + r'(?:\.' + IDENT + r')*)', raw.strip(), re.I) if m: return 'см. ' + m.group(1) m = re.match(r'\s*(' + IDENT + r'(?:\.' + IDENT + r')*)', raw.strip()) return m.group(1) if m else None def main(): ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) ap.add_argument('--docs', action='append', required=True, metavar='ВЕРСИЯ=КАТАЛОГ', help='скрап документации ИТС; можно указать несколько раз') ap.add_argument('--lib', action='append', required=True, metavar='[ВЕРСИЯ=]КАТАЛОГ', help='каталог, куда v8unpack развернул 1Cv8.cf. С префиксом версии ' 'привязывается к своей документации; без префикса берется для всех') ap.add_argument('--out', required=True, metavar='ФАЙЛ.jsonl') ap.add_argument('--map', metavar='ФАЙЛ.md', help='заодно переписать карту подсистем') ap.add_argument('--purposes', metavar='ФАЙЛ.json', help='свои однострочные формулировки назначения: "Модуль.Метод": "текст"') args = ap.parse_args() # Каждая версия документации сшивается со СВОЕЙ библиотекой. Иначе методы, убранные в новой # версии, объявляются несуществующими, а добавленные - неподтвержденными. libs, default_lib = {}, None for spec in args.lib: ver, sep, path = spec.partition('=') if not sep: ver, path = None, spec impl = parse_impl(path) index = collections.defaultdict(list) for cid, c in impl.items(): for m in c['methods']: index[m['name'].lower()].append(cid) sys.stderr.write('реализация %s: контейнеров %d, экспортных методов %d\n' % (ver or 'общая', len(impl), sum(len(c['methods']) for c in impl.values()))) if ver: libs[ver] = (impl, index) else: default_lib = (impl, index) # Библиотеку без префикса версии подставляем любой документации. Молча подставлять вместо нее # "самую свежую из указанных" нельзя: опечатка в версии тогда сведет документацию с чужой # реализацией и выдаст неверные модули и контексты - ровно то, ради чего версии и разводились. # Формулировки назначения - единственная часть справочника, написанная нами, а не выведенная # из источников. Два раздела: чем занят модуль и что делает метод. purposes, mod_purposes = {}, {} if args.purposes and os.path.exists(args.purposes): p = json.load(io.open(args.purposes, encoding='utf-8')) if isinstance(p, dict) and ('methods' in p or 'modules' in p): purposes = p.get('methods') or {} mod_purposes = p.get('modules') or {} else: purposes = p sys.stderr.write('формулировки назначения: модулей %d, методов %d\n' % (len(mod_purposes), len(purposes))) merged, seen, versions, per_version = {}, collections.defaultdict(set), [], {} stat = collections.Counter() for spec in args.docs: if '=' not in spec: raise SystemExit('--docs ждет ВЕРСИЯ=КАТАЛОГ, получено: %s' % spec) ver, path = spec.split('=', 1) versions.append(ver) pair = libs.get(ver, default_lib) if pair is None: raise SystemExit('для документации %s не указана библиотека: добавьте --lib "%s=<каталог>" ' 'либо --lib <каталог> без версии. Известны: %s' % (ver, ver, ', '.join(sorted(libs)) or 'ни одной')) impl, by_name = pair pages = parse_docs(path) for d in pages: module, source = resolve_module(d, impl, by_name) d['module'], d['module_source'] = module, source stat[source] += 1 stat['всего'] += 1 key = (module or '?', d['name']) seen[key].add(ver) merged[key] = d per_version.setdefault(key, {})[ver] = d sys.stderr.write('документация %s: методов %d\n' % (ver, len(pages))) resolved = sum(v for k, v in stat.items() if k in SRC_CODE) sys.stderr.write('сшивка: модуль определен у %d из %d (%.1f%%)\n' % (resolved, stat['всего'], 100.0 * resolved / max(1, stat['всего']))) for k, v in stat.most_common(): if k != 'всего' and k not in SRC_CODE: sys.stderr.write(' не разрешено - %s: %d\n' % (k, v)) used = sorted({k[0] for k in merged}) header = {'_': 'справочник API БСП', 'versions': versions, 'modules': {}} # Свойства модуля берутся из самой поздней библиотеки, где он есть: модуль мог быть убран, # и тогда о нем знает только более ранняя. lookup = [libs[v][0] for v in reversed(versions) if v in libs] if default_lib is not None: lookup.append(default_lib[0]) for cid in used: c = next((L[cid] for L in lookup if cid in L), None) header['modules'][cid] = { 'kind': c['kind'] if c else '?', 'av': ''.join(AV_SHORT.get(a, '?') for a in c['availability']) if c else '', 'reuse': c['reuse'] if c else None, 'total': len(c['methods']) if c else 0, } if mod_purposes.get(cid): header['modules'][cid]['o'] = mod_purposes[cid] unknown = sorted(set(mod_purposes) - set(header['modules'])) if unknown: sys.stderr.write('в формулировках есть модули, которых нет в справочнике: %s\n' % ', '.join(unknown[:5])) unknown_m = sorted(set(purposes) - {'%s.%s' % k for k in merged}) if unknown_m: sys.stderr.write('в формулировках есть методы, которых нет в справочнике: %d, например %s\n' % (len(unknown_m), ', '.join(unknown_m[:3]))) with io.open(args.out, 'w', encoding='utf-8', newline='\n') as fh: fh.write(json.dumps(header, ensure_ascii=False, sort_keys=False) + '\n') for (mod, name), d in sorted(merged.items()): rec = {'m': mod, 'n': name, 'k': 'Ф' if d['kind'].lower().startswith(('функ', 'func')) else 'П', 'sig': d['signature'], 'av': ''.join(AV_SHORT.get(a, '?') for a in d['availability']), 'sub': d['subsystem'], 'sec': 'П' if d['section'] == 'Переопределение' else 'И', 'src': SRC_CODE.get(d['module_source'], '?'), 'v': sorted(seen[(mod, name)])} if d['async']: rec['async'] = True if d['group']: rec['grp'] = d['group'] params = [] for p in d['params']: q = {'n': p['name']} if p.get('type'): q['t'] = p['type'] if p.get('default'): q['d'] = p['default'] if p.get('byval'): q['byval'] = True params.append(q) if params: rec['p'] = params rt = return_type(d.get('returns')) if rt: rec['ret'] = rt pur = purposes.get(mod + '.' + name) if pur: rec['o'] = pur was = version_deltas(per_version.get((mod, name), {}), versions, rec) if was: rec['was'] = was fh.write(json.dumps(rec, ensure_ascii=False, sort_keys=False) + '\n') sys.stderr.write('записано: %s, методов %d, %.2f МБ\n' % (args.out, len(merged), os.path.getsize(args.out) / 1048576.0)) if args.map: write_subsystem_map(args.map, merged, versions) sys.stderr.write('записано: %s\n' % args.map) def write_subsystem_map(path, merged, versions): """Карта подсистем: какие модули в каждой и где ее точки расширения. Имя подсистемы в документации и имя модуля в коде совпадают далеко не всегда, а без карты приходится угадывать: механизм печати живет в УправлениеПечатью, а не в Печать. """ by_sub = collections.defaultdict(lambda: collections.defaultdict(int)) for (mod, name), d in merged.items(): by_sub[d['subsystem']][mod] += 1 lines = ['# Карта подсистем БСП', '', 'Собрано генератором из версий: %s. Правка вручную бессмысленна - файл ' 'перезаписывается при пересборке справочника.' % ', '.join(versions), '', 'Имя подсистемы в документации и имя модуля в коде совпадают не всегда: механизм ' 'печати живет в `УправлениеПечатью`, свойства - в `УправлениеСвойствами`, а базовая ' 'функциональность - в `ОбщегоНазначения`. Поэтому модуль ищется по этой таблице, а не ' 'по названию подсистемы.', '', 'Цифра в скобках - сколько методов подсистемы объявлено в этом модуле.', '', '| Подсистема | Программный интерфейс | Точки расширения |', '|---|---|---|'] for sub in sorted(by_sub, key=lambda s: (-sum(by_sub[s].values()), s)): mods = by_sub[sub] api = [m for m in mods if 'Переопределяем' not in m and m != '?'] ext = [m for m in mods if 'Переопределяем' in m] api.sort(key=lambda m: (-mods[m], m)) ext.sort(key=lambda m: (-mods[m], m)) lines.append('| %s | %s | %s |' % (sub, map_cell(api, mods), map_cell(ext, mods))) lines.append('') with io.open(path, 'w', encoding='utf-8', newline='\n') as fh: fh.write('\n'.join(lines)) def map_cell(mods, counts, top=10): """Ячейка карты. В крупных подсистемах модулей десятки, и целиком они превращают строку таблицы в простыню. Перечисляются те, где методов больше; остальные считаются, а полный состав дает scripts/bsp-api.py subsystem.""" if not mods: return '-' head = ', '.join('`%s` (%d)' % (m, counts[m]) for m in mods[:top]) rest = len(mods) - top return head + (', и еще %d' % rest if rest > 0 else '') if __name__ == '__main__': main()
-
-
SKILL.md 14.7 KB
--- name: 1c-bsp-api description: "Справочник программного интерфейса Библиотеки стандартных подсистем (БСП) 1С - какие общие модули существуют, какие у них экспортные методы, сигнатуры, типы параметров, контексты выполнения и переопределяемые обработчики. Используй когда пишешь код на конфигурации с БСП и нужно узнать имя модуля или метода, его сигнатуру, серверный он или клиентский, какой переопределяемый обработчик реализовать под задачу; а также чтобы ПРОВЕРИТЬ вызов перед тем, как его написать: имя модуля БСП, отсутствующее в библиотеке, по виду не отличается от настоящего, поэтому вызов сверяется со справочником. Работает офлайн, платформа и EDT не нужны. НЕ для API самой платформы (там 1c-platform-docs) и НЕ для прикладных конфигураций ERP, ЗУП, БП" argument-hint: "find <текст> | show <Модуль.Метод> | check <Модуль.Метод> | module <Имя> | subsystem <Имя> | overrides <текст>" allowed-tools: - Bash - Read --- # Справочник API БСП Офлайн-справочник по программному интерфейсу БСП: 2624 метода в 284 модулях, 71 подсистема, версии 3.1.11 и 3.2.1. Собран из двух источников одновременно - структура и сигнатуры из документации, модули и экспортность из самой библиотеки. Каждая версия документации сведена со своим дистрибутивом, поэтому различия между версиями видны, а не усреднены. Назначение написано нами: одна строка у каждого из 284 модулей и у 440 методов ядра. Описательный текст документации ИТС в справочник не переносится. Справочник больше мегабайта, в контекст целиком не грузится. Он спрашивается по месту. ## Главное правило **Не пиши вызов метода БСП, не проверив его.** Имена в БСП длинные и составные, поэтому правдоподобная выдумка выглядит как настоящее имя. Классические несуществующие: `ФайловаяСистемаКлиентСервер`, `JSONСтрокой`, `Пользователи.СсылкаТекущегоПользователя`. ```bash python skills/1c-bsp-api/scripts/bsp-api.py check ФайловаяСистемаКлиентСервер.ПолучитьФайл ``` Код возврата 1, если вызова нет. При промахе инструмент подсказывает похожие имена - и по модулю, и по методу. ## Как устроена библиотека **Суффикс имени модуля - это контекст выполнения, а не тематика.** Один механизм разложен по нескольким модулям, и выбор между ними определяется тем, откуда идет вызов: | Суффикс | Где исполняется | Пример | |---|---|---| | без суффикса или `Сервер` | сервер, толстый клиент, внешнее соединение | `ОбщегоНазначения` | | `Клиент` | тонкий и толстый клиент | `ОбщегоНазначенияКлиент` | | `КлиентСервер` | и там, и там | `ОбщегоНазначенияКлиентСервер` | | `ВызовСервера` | сервер, вызывается с клиента напрямую | `ОбщегоНазначенияВызовСервера` | Отсюда частая ошибка: серверный метод вызывают из клиентского кода. Контекст каждого метода есть в справочнике, отбор - ключом `--av` (`S` сервер, `T` тонкий, `F` толстый, `E` внешнее соединение, `C` вызов сервера). **Три вида модулей по назначению:** - **Обычные** - публичный интерфейс, их и вызывают: `ОбщегоНазначения`, `Пользователи`, `УправлениеПечатью`. - **`Переопределяемый`** - точки расширения. Их не вызывают, в них ПИШУТ: обработчик вызывает библиотека, а тело пишет внедряющая конфигурация. Таких методов 372. - **`Служебный`** - внутренняя реализация библиотеки. В программный интерфейс не входит ни один служебный метод, и вызывать их нельзя: они меняются между версиями без объявления. Еще два суффикса встречаются реже: `ПовтИсп` - модуль с повторным использованием возвращаемых значений, `Локализация` - национальная специфика. **Часть интерфейса объявлена не в общих модулях.** Обмен данными опубликован модулями объектов обработок (`Обработка.УниверсальныйОбменДаннымиXML`, `Обработка.КонвертацияОбъектовXDTO`). В справочнике они есть наравне с общими модулями. ## Запросы ```bash B=skills/1c-bsp-api/scripts/bsp-api.py python $B find печать # поиск по имени, модулю, подсистеме, назначению python $B find "реквизит объект" # ищутся все слова запроса сразу, не подстрока python $B find файл --av T # только то, что доступно на тонком клиенте python $B show ОбщегоНазначения.ЗначениеРеквизитаОбъекта # карточка метода python $B show ЗначениеРеквизитаОбъекта # все модули, где есть метод с таким именем python $B module Пользователи # состав модуля целиком python $B modules контакт # какие вообще есть модули python $B subsystem печать # модули и механизмы подсистемы python $B overrides обновлен # переопределяемые обработчики под задачу python $B check Пользователи.ТекущийПользователь python $B stats # что вообще в справочнике ``` Общие ключи отбора: `--av`, `--sub <подсистема>`, `--version 3.2.1`, `--limit N`. ## Как читать выдачу Строка вида `ОбщегоНазначения.ЗначениеРеквизитаОбъекта SFE` - это модуль, метод и контексты. **Пометка `[?]` означает, что модуль выведен, а не подтвержден.** Документация БСП называет механизм, а не модуль, поэтому у части методов модуль восстановлен по примеру вызова или по совпадению контекстов. В карточке (`show`) последняя строка всегда говорит, откуда взято имя модуля. Метод с пометкой перед использованием стоит сверить с конфигурацией проекта. Пометка стоит у 117 методов из 2624, это около четырех процентов. Еще у 37 модуль определить не удалось вовсе - они собраны под именем `?`. Это не значит, что метода нет: значит, одно и то же имя объявлено в нескольких модулях, и документация не говорит, о каком из них статья. **Пометка `[!]` означает, что между версиями метод изменился.** Карточка тогда содержит строку "ВНИМАНИЕ, в <версия> иначе" с прежней сигнатурой. Таких методов 27, и часть изменений ломающие: `ОбщегоНазначения.ВыполнитьМетодКонфигурации` из процедуры стал функцией, а у `ДобавитьПоказатель` новый параметр вставлен не в конец, а первым. Код, написанный по новой сигнатуре, на старой версии передаст аргументы не туда и об этом не сообщит. ## Частые ошибки - **Выдуманный модуль.** Проверять `check`, а не полагаться на память. - **Серверный метод в клиентском коде.** Смотреть контексты; для клиента почти всегда есть парный модуль с суффиксом `Клиент`. - **Вызов служебного модуля.** Если в имени есть `Служебный` - это не интерфейс. - **Попытка вызвать переопределяемый обработчик.** В него пишут тело, а не вызывают его. - **Метод из другой версии.** У каждой записи указано, в каких версиях БСП она есть. Метод, помеченный только `3.2.1`, на 3.1.11 не существует. А метод с пометкой `[!]` существует в обеих, но вызывается по-разному - смотреть карточку до того, как писать вызов. - **Расчет на то, что у метода тот же набор параметров, что был раньше.** Сигнатура в справочнике полная, включая значения по умолчанию - брать оттуда. ## Границы Справочник знает ИМЕНА, СИГНАТУРЫ и КОНТЕКСТЫ, а назначение - строкой, написанной нами. Развернутого описания в нем нет: текст документации ИТС лицензионный и сюда не переносится. Строка назначения есть у каждого модуля, но у методов пока только у ядра - базовых модулей `ОбщегоНазначения*`, длительных операций, пользователей, строковых функций, файловой системы и журнала регистрации. Когда нужно понять механизм глубже, а не форму вызова - идти в документацию ИТС по подсистеме, которую покажет `subsystem`. Не покрыты: HTTP-сервисы и веб-сервисы библиотеки, макеты, роли, права, состав метаданных подсистем. Только программный интерфейс кода. ## Сборка справочника Готовый справочник лежит в `references/bsp-api.jsonl` и обновлять его нужно только при переходе на новую версию БСП. Пересборка требует двух источников, оба лицензионные и в репозиторий не входят: скрапа документации с ИТС и дистрибутива библиотеки. ```bash python -m v8unpack -E 1Cv8.cf E:\bsp\3_2_1 --temp E:\bsp\_tmp # распаковать дистрибутив python skills/1c-bsp-api/scripts/bsp-build.py \ --docs "3.1.11=E:\scrape\bsp3111doc" --docs "3.2.1=E:\scrape\bsp321doc" \ --lib "3.1.11=E:\bsp\3_1_11" --lib "3.2.1=E:\bsp\3_2_1" \ --purposes skills/1c-bsp-api/references/purposes.json \ --out skills/1c-bsp-api/references/bsp-api.jsonl \ --map skills/1c-bsp-api/references/subsystem-map.md ``` Формулировки назначения ведутся отдельно, в `references/purposes.json`: раздел `modules` и раздел `methods` с ключами вида `Модуль.Метод`. При сборке они подмешиваются в справочник, а имена, которых в нем нет, генератор называет в отчете - это ловит и опечатку, и формулировку к методу, которого в этой версии уже не существует. Ключи `--docs` и `--lib` указываются по одному на версию и связываются префиксом. Связывать обязательно: если сшивать документацию 3.1.11 с библиотекой 3.2.1, методы, убранные в новой версии, будут объявлены несуществующими. Библиотека без префикса версии берется для всех. Брать надо `1Cv8.cf` - чистую библиотеку, а не `1Cv8_demo.cf`: демонстрационная конфигурация несет объекты, которых в поставке нет. Распаковка идет без платформы и Конфигуратора. Скрипты на Python, PowerShell-порта нет: сборка нужна редко, а поиск идет по готовому файлу.
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.