Перейти к содержимому

Создание пользовательского блока

Описание

Создание пользовательского блока — это процесс создания нового блока в Puzzle RPA, который позволяет пользователям создавать свои собственные блоки для использования в процессах.

Перечень действий для создания пользовательского блока

  1. Требуется создать папку с именем блока (например hello_my_block).
  2. Внутри папки создать структуру файлов (см. ниже).
  3. Наполнить файлы block.json, values.xml, code.value.py (или code.py), meta.json, libs.py.json, typeToName.json.
  4. Добавить код в src/__init__.py.
  5. (Опционально) Указать зависимости в requirements.txt и поместить готовые wheels в wheels/.
  6. Импортировать папку в Puzzle RPA через Настройки → Расширения.
  7. Перезагрузить Puzzle RPA и проверить блок в тулбоксе.

Структура папки блока

hello_my_block/ # имя папки - обычно совпадает с type блока
├─ block.json
├─ code.value.py # или code.py
├─ meta.json
├─ libs.py.json
├─ values.xml
├─ typeToName.json
├─ requirements.txt # опционально
├─ wheels/ # опционально, *.wls файлы
└─ src/ # папка для python - скриптов и вспомогательных файлов
└─ __init__.py

Назначение файлов

  • block.json - JSON-описание внешнего вида блока;
  • code.value.py / code.py - строка/код, который будет встраиваться в сгенерируемый Python (вызов функции из code-storage-py);
  • libs.py.json - список импортируемых модулей из code-storage-py;
  • meta.json - режим, флаги логирования и поведение генерации;
  • values.xml - XML-описание разъёмов/тулбокса (shadow/начальные блоки);
  • typeToName.json - отображаемое название блока для логов/информации;
  • requirements.txt - файл описывающий дополнительные python библиотеки и их версии которые используются блоком;
  • wheels/ - папка с wheel-пакетами которые используются блоком;
  • src/ - папка для python - скриптов и вспомогательных файлов;
  • src/__init__.py - реализация функций, вызываемых блоком (c декораторами логгера).

Создание файла block.json

  • type - уникальное имя блока; должно совпадать с именем папки и с <block type="..."> в values.xml.
  • message0 - текст блока; параметры (разъёмы блока) указываются как %1, %2 и т.д. Например, “Умножить %1 на 2”.
  • args0: массив описаний разъёмов/полей.
  • inputsInline: true/false — располагает ли разъёмы в одну строку.
  • output- ключ со значением null для блока возвращающего значение.
  • previousStatement- ключ со значением null для блока который может иметь предыдущее соединение сверху (обозначенное выемкой).
  • nextStatement- ключ со значением null для блока который следующее соединение снизу (обозначенное вкладкой).
  • colour: цвет блока в HEX.
  • tooltip - текст подсказки который будет отображаться при наведении на блок.
  • helpUrl - URL справки по блоку.

Пример block.json для блока, который умножает число на 2:

{
"type": "hello_double",
"message0": "Умножить %1 на 2 %2",
"args0": [
{
"type": "input_value",
"name": "VALUE1"
},
{
"type": "input_dummy"
}
],
"inputsInline": true,
"output": null,
"colour": "#4A90E2",
"tooltip": "Умножает число на 2",
"helpUrl": ""
}

Примечания и типичные параметры args0

  • input_dummy - пустая строка/видимый текст в блоке (используется для описаний).
{
"type": "input_dummy"
}
  • input_value - поле для подсоединения блока со значением (value).
{
"type": "input_value",
"name": "VALUE1"
}
  • input_statement - для вложенных блоков (statement/тело).
{
"type": "input_statement",
"name": "DO"
}
  • field_dropdown - выпадающий список (нужны опции в options).
{
"type": "field_dropdown",
"name": "MODE",
"options": [
[
"Опция A",
"A"
],
[
"Опция B",
"B"
]
]
}
  • field_checkbox - чекбокс (логическое значение).
{
"type": "field_checkbox",
"name": "ENABLED",
"checked": true
}
  • field_number- числовое поле.
{
"type": "field_number",
"name": "NUM",
"value": 10,
"min": 0,
"max": 100,
"precision": 1
}
  • field_text- текстовое поле.
{
"type": "field_text",
"name": "TEXT",
"text": "Пример"
}
  • field_variable - поле переменных.
{
"type": "field_variable",
"name": "VAR",
"variable": "item"
}
  • field_code_editor - поле для редактирования кода.
{
"type": "field_code_editor",
"name": "CODE"
}
  • field_image - поле для отображения изображения (Требуется base64 строка изображения, width и height в пикселях, alt - текст изображения когда блок свернут).
{
"type": "field_image",
"src": "data:image/png+xml;base64,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",
"width": 25,
"height": 25,
"alt": "SQL"
}

Создание файла code.value.py / code.py

  • Если блок возвращает значение — используем code.value.py.
  • Если блок не возвращает значение — используем code.py.

Синтаксис (строка, которая будет вставлена в сгенерированный код)

  • ${vc('VALUE1')} - метка для кодогенерации: значение из разъёмов типа input_value.
  • ${fv('FIELD1')} - метка для кодогенерации: значение из полей типа field_text, field_number, field_variable, field_dropdown, field_checkbox.
  • ${sc('DO')} - метка для кодогенерации: код из блока типа input_statement (для вложенных блоков).
  • #isInternalLog - специальный маркер для передачи параметра логирования (обычно последний аргумент).

Пример code.value.py (вызов функции из модуля hello_double):

hello_double.double_value(${vc('VALUE1')},#isInternalLog)

Примечания:

  • Если нужно передать несколько аргументов — перечислить: ${vc('VALUE1')}, ${vc('VALUE2')}.
  • Если требуется обернуть значения полей типа fv в кавычки, то используйте '${fv('FIELDVALUE1')}'

Создание файла libs.py.json

  • Формат: JSON-массив путей модулей, которые нужно импортировать в сгенерированный код (модули из code-storage-py).
  • Префикс $/ означает путь внутри code-storage (пример используемой практики).

Пример:

[
"$/hello_double"
]

Примечания:

  • Откуда брать имена? — соответствуют именам модулей в code-storage-py.

Создание файла meta.json

Описание ключей:

  • _mode со значением "value" — блок возвращает значение (используется code.value.py).
  • _isInternalLog со значением true/false — включить внутреннее логирование для блока.
  • _isDontUseLogger со значением true — блок не должен писать лог (подавляет логирование).
  • _onIfUseFunc со значением false — устаревший флаг (требуется всегда указывать false).

Пример:

{
"_mode": "value",
"_isInternalLog": true,
"_onIfUseFunc": false,
}

Условия использования ключей:

ЗадачаРекомендация
Блок возвращает значение_mode: "value"
Блок просто выполняет действиене указывать _mode
Нельзя логировать_isDontUseLogger: true
Лог нужен_isInternalLog: true

Создание файла typeToName.json

  • Служит для записи читаемого названия блока в логах.
  • Формат: {"type_name": "Читаемое название"}.

Пример:

{
"hello_double": "Умножить число на 2"
}

Создание файла values.xml

  • Описывает как блок выглядит в тулбоксе, какие теневые блоки (shadow) или обычные блоки (block) подставлять в разъёмы блока.

Пример описания блока hello_double в values.xml:

<block type="hello_double">
<value name="VALUE1">
<shadow type="math_number">
<field name="NUM">2</field>
</shadow>
</value>
</block>

Примеры разных типов полей в values.xml

<!-- Текстовое поле -->
<shadow type="text">
<field name="TEXT"></field>
</shadow>
<!-- Числовое поле -->
<shadow type="math_number">
<field name="NUM">10</field>
</shadow>
<!-- Переменная -->
<block type="variables_get">
<field name="VAR">myVar</field>
</block>

Создание файла requirements.txt и wheels/

  • Если блок использует библиотеки, отсутствующие в окружении Puzzle RPA, укажите их в файле requirements.txt.
  • В папке wheels/ размещаются собранные .whl файлы совместимых с версией Python (3.11) и операционной системой.

Рекомендации:

  • Минимизируйте внешние зависимости.
  • Если библиотека уже присутствует в Puzzle RPA — не добавляйте её в файл requirements.txt, чтобы не вызвать конфликты.
  • В документации/репозитории проекта храните актуальный список предустановленных библиотек.

Пример содержимого файла requirements.txt:

pandas==2.2.3
numpy==1.24.3

Создание файла src/__init__.py — реализация функций

  • Внутри находятся функции, которые вызываются из файлов code.value.py/code.py.
  • Для логирования используются декораторы из модуля puzzle_logger.

Пример реализации:

from puzzle_logger import log_decorator, window_logger
@window_logger
@log_decorator
def double_value(value, puzzle_logger_path=None, block_text=None, block_id=None, window_log=False, **kwargs):
if isinstance(value, (int, float)):
return value * 2
if isinstance(value, str):
try:
return float(value) * 2
except ValueError:
raise ValueError(f"Некорректный аргумент: '{value}' не является числом")
raise TypeError(f"Тип '{type(value).__name__}' не поддерживается")

Примечания:

  • Всегда ставьте параметры puzzle_logger_path=None, block_text=None, block_id=None, window_log=False после основных параметров, если хотите корректный лог.
  • Логирование и обработка ошибок важны для поддержки и диагностики блока.

Типичные ошибки и как их избежать

  • Не совпадают имена: type в block.json, имя в typeToName.json и <block type> в values.xml должны совпадать — иначе блок не подключится или не будет логироваться. Имя папки с файлами расширения должно соответствовать type в block.json.
  • Неправильный формат JSON — синтаксис JSON, пути к модулям должны быть корректны.
  • Запутанные зависимости — разные версии библиотек в requirements.txt могут конфликтовать с системными. Тестируйте на отдельном стенде.
  • Отсутствуют ключи описания полей или функции не экспортируются — убедитесь, что функция и ключи описания полей существуют и их имена совпадают с вызовом в code.value.py/code.py.
  • Блок не появляется в тулбоксе — в чём причина? Часто: ошибки в values.xml, несовпадение type, синтаксическая ошибка в block.json.

Минимальный шаблон (готовые файлы) — папка hello_double

  1. Скачать пример блока — hello_double.zip — и распаковать архив в папку блока (например hello_double). Либо создать папку и файлы вручную по этой инструкции.
  2. Импортировать папку в Puzzle RPA: “Настройки → Расширения”.

Файл: block.json

{
"type": "hello_double",
"message0": "Умножить %1 на 2 %2",
"args0": [
{
"type": "input_value",
"name": "VALUE1"
},
{
"type": "input_dummy"
}
],
"inputsInline": true,
"output": null,
"colour": "#4A90E2",
"tooltip": "Умножает число на 2",
"helpUrl": ""
}

Файл: values.xml

<block type="hello_double">
<value name="VALUE1">
<shadow type="math_number">
<field name="NUM">2</field>
</shadow>
</value>
</block>

Файл: code.value.py

hello_double.double_value(${vc('VALUE1')},#isInternalLog)

Файл: libs.py.json

[
"$/hello_double"
]

Файл: meta.json

{
"_mode": "value",
"_isInternalLog": true,
"_onIfUseFunc": false,
}

Файл: typeToName.json

{
"hello_double": "Умножить на 2"
}

Файл: __init__.py

from puzzle_logger import log_decorator, window_logger
@window_logger
@log_decorator
def double_value(value, puzzle_logger_path=None, block_text=None, block_id=None, window_log=False, **kwargs):
if isinstance(value, (int, float)):
return value * 2
if isinstance(value, str):
try:
return float(value) * 2
except ValueError:
raise ValueError(f"Некорректный аргумент: '{value}' не является числом")
raise TypeError(f"Тип '{type(value).__name__}' не поддерживается")