Использование Python#
Введение#
Платформа предоставляет возможность использовать Python для различных целей, благодаря его удобству и широкому распространению как языка сценариев и программирования. Сценарии Python на платформе должны соответствовать версии 3.0, как описано в официальной документации Python. Полное руководство разработчика доступно в Руководстве разработчика Python.
Python на платформе называется Iron Python, обеспечивающим взаимодействие с кодом C#. Он включает в себя две основные библиотеки - clr
и system
, которые обеспечивают доступ к сущностям платформы.
Меню библиотеки Python#
В этом меню вы можете добавлять общие модули Python, которые становятся доступными на front-end (в Component Script) и на back-end (в шаге Execute Script для dataflow).
Просмотр общих модулей Python#
В меню “Python modules” отображается список уже добавленных модулей, включая информацию о доступности модуля для front-end, back-end или обоих.
Добавление нового модуля#
При нажатии на кнопку “Add” открывается окно добавления нового модуля.
В этом окне вы можете:
Выбрать тип доступности нового модуля (front, back или both).
Указать имя нового модуля для импорта.
Вставить и проверить код модуля через “Compile”.
Платформа и Python#
Python может использоваться как часть Component Script для каждого компонента, позволяя контролировать формы приложений, а также как часть Dataflow через шаг Execute Script.
Функции могут быть вызваны различными способами, например, одним из контролей UI при наступлении определенных событий.
Для доступа к компонентам платформы необходимо импортировать библиотеки IronPython (clr
и system
) и использовать системную переменную context
.
context.Model
& context.DataModel
#
context.Model
&context.DataModel
предоставляют доступ к различным полям данных модели Platform.Рекомендуется использовать
context.DataModel
для доступа к настраиваемым полям иcontext.Model
для доступа к внутренним полям компонента по умолчанию.
context.Properties
#
context.Properties
позволяет управлять элементами управления пользовательского интерфейса, например, изменять их видимость или доступность. Пример:
context.Properties.<Internal_UI_Control_Name>. =
context.Form
#
context.Form
используется для доступа к данным формы или управления визуальным представлением формы, например, для настройки сообщений об ошибках.
Доступные функции:
context.Form.Get().SetValue()
— устанавливает значение для определенного элемента управления пользовательского интерфейса в текущей форме.context.Form.Get().AddError()
— устанавливает сообщение об ошибке, отображаемое под определенным элементом управления пользовательского интерфейса в текущей форме.context.Form.Get().ClearError()
— очищает сообщение об ошибке, показанное под конкретным элементом управления пользовательского интерфейса в текущей форме.
Пример:
if datamodel.InvoiceName == 'PLEASE_SET_A_UNIQUE_NAME':
context.Form.Get("InvoiceName").AddError("Please set a unique invoice name")
else:
context.Form.Get("InvoiceName").ClearError()
context.Commands
#
context.Commands
можно использовать для управления пользовательским интерфейсом исполняемого в данный момент компонента, изменения содержимого текущей формы, открытия разных страниц, открытия новых компонентов, возврата на предыдущую страницу или даже запуска новых Workflows, Dataflows или Scripts.
Примеры доступных функции context.Commands:
context.Commands.AddItem (GUID)
: Добавить элемент управления пользовательским интерфейсом на страницу с помощью GUID.context.Commands.ChangePageAsync (GUID)
: Открыть страницу, используя ее GUID.context.Commands.ChangePageByName ("ИмяСтраницы")
: Измените текущую страницу компонента на новую страницу, используя внутреннее имя.context.Commands.OpenComponent (GUID ComponentID, GUID PageID)
: Открыть новый компонент и определенную страницу внутри компонента.context.Commands.EditItem (GUID UI_ControlID, EntityId)
: Смещение фокуса пользовательского интерфейса на конкретный элемент управления пользовательского интерфейса и определенные данные (используя его внутренний идентификатор).context.Commands.ExecuteWorkflow (GUID WorkflowID)
: Выполнить workflow, используя его идентификатор.context.Commands.ExecuteDataflow (GUID DataflowID, ContextID)
: Выполнить dataflow, используя его GUID и указанный контекст данных.context.Commands.ExecuteScript ("ScriptName", "ScriptParams")
: Выполнить скрипт (функцию) из Component Script с некоторыми параметрами.
context.Logger
#
Функции из context.Logger
позволяют записывать информацию из Component Script в консоль браузера.
Текущая версия context.Logger
включает в себя следующие методы, которые отличаются тем, как соответствующие сообщения показываются в консоли браузера (например, Info - черный цвет, Error - красный цвет и т.д.):
context.Logger.Info(String)
: Записывает информационное сообщение в консоль браузера.context.Logger.Error(String)
: Записывает сообщение об ошибке в консоль браузера.context.Logger.Trace(String)
: Записывает трассировочное сообщение в консоль браузера.context.Logger.Error(Exception, String)
: Записывает сообщение об ошибке и информацию об исключении в консоль браузера.
Пример функции из Component Script, которая выводит строку “Show model info” и значение поля Property_1
:
def show_model_info(model):
context.Logger.Info("show_model_info")
context.Logger.Info("Property Property_1=" + model.Data.Property_1)
context.PlatformServices
#
Обновлено до версии 0.7.0
Функции context.PlatformServices
включают в себя широкий набор функций, доступных на различных платформах (web, mobile), плюс функции по построению и показу модальных окон и окон типа sidebar.
Следующие методы доступны как часть context.PlatformServices
:
context.PlatformServices.Device()
: Возвращает тип устройства (Browser, Android, iOS).context.PlatformServices.FingerpintAvailible()
: ВозвращаетTrue
, если есть сканер отпечатка пальцев.context.PlatformServices.EnableFingerpint()
: Разрешает сканер отпечатка пальцев.context.PlatformServices.DisableFingerpint()
: Запрещает сканер отпечатка пальцев.context.PlatformServices.FingerpintEnabled()
: Проверяет, разрешен ли сканер отпечатка пальцев.context.PlatformServices.SetAppLock()
: Устанавливает lock на приложение.context.PlatformServices.ChangeAppPinLock()
: Устанавливает PIN на lock на приложение.context.PlatformServices.AppLockEnabled()
: Проверяет, установлен ли lock на приложение.context.PlatformServices.ScanBarcode(BarcodeType)
: Сканирует баркод по выставленному типу.context.PlatformServices.OpenUrl(“url”)
: Открывает новую закладку в браузере по предоставленному URL.context.PlatformServices.OpenFromBase64Url(url)
: Открывает новую закладку в браузере по предоставленному Base64 URL.context.PlatformServices.OpenApp(appUrl)
: Открывает приложение по предоставленному URL.context.PlatformServices.CanOpenApp(params string[] appUrls)
: Проверка возможности открытия приложения на устройстве.context.PlatformServices.CanUsePayment()
: Проверка возможности оплаты.context.PlatformServices.StartPayment()
: Запускает процесс оплаты.context.PlatformServices.SMSRetriever()
: Позволяет получить SMS.context.PlatformServices.ShowDialog(string message, string title)
: Показывает простой диалог с кнопкой ОК.context.PlatformServices.ShowDialog(ComponentID, title, hSize, vSize, style)
: Показывает простой диалог по ID компонента с заданными размерами, заголовком и передачей CSS стилей.context.PlatformServices.Confirm(string message, string title = “”)
: Показывает диалог с кнопками Yes/No.context.PlatformServices.GeolocationPosition()
: Возвращает текущую геолокацию.
Пример использования context.PlatformServices.GeolocationPosition
:
def Success(coords):
context.Logger.Error("Get coords complete")
if (coords == None):
context.Logger.Error("Coords null")
context.Logger.Error("Langitude " + "{:.2f}".format(coords.Latitude))
context.Logger.Error("Longitude " + "{:.2f}".format(coords.Longitude))
def Error(exception):
context.Logger.Error(exception, "Get coords error")
def GetCoords():
context.PlatformServices.GeolocationPosition().Subscribe(lambda coords: Success(coords), lambda ex: Error(ex))
Пример использования функции context.PlatformServices.Confirm
:
def checkResponse(task):
if (task.Result == True):
context.Logger.Error("TRUE")
else:
context.Logger.Error("FALSE")
def show_modal():
explicitSystemAction = System.ActionSystem.Threading.Tasks.Task[System.Boolean]
result = context.PlatformServices.Confirm("Your Message", "Dialog Title").ContinueWith(explicitSystemAction)
Следующая группа функций используется для определения того, на каком устройстве и в каком разрешении открыт интерфейс у текущего пользователя:
context.PlatformServices.IsDesktop()
: ВозвращаетTrue
, если интерфейс открыт на десктопе.context.PlatformServices.IsMobile()
: ВозвращаетTrue
, если интерфейс открыт на мобильном устройстве.context.PlatformServices.IsExtraSmall()
: ВозвращаетTrue
, если интерфейс открыт на экране размером меньше 576px.context.PlatformServices.IsSmall()
: ВозвращаетTrue
, если интерфейс открыт на экране размером больше 576px.context.PlatformServices.IsMedium()
: ВозвращаетTrue
, если интерфейс открыт на экране размером больше 768px.context.PlatformServices.IsLarge()
: ВозвращаетTrue
, если интерфейс открыт на экране размером больше 992px.context.PlatformServices.IsExtraLarge()
: ВозвращаетTrue
, если интерфейс открыт на экране размером больше 1200px.
context.PlatformServices.Sidebar.Builder
#
context.PlatformServices.Sidebar.Builder
используется для создания окон, открывающихся в одной из заданных позиций относительно главного окна (формы) приложения - сверху, снизу, справа или слева.
Перед так как sidebar может быть вызван, он должен быть построен следующим образом:
def open_sidebar(position):
dialog_builder = context.PlatformServices.SidebarBuilder('4b7675ae-406a-45bd-9bf9-526cc78ce476')
dialog_builder.WithEntryId(1).WithTitle("Open for test").WithPageId('8bd5310a-b7ff-4f65-bc38-3f4c20058483')
dialog_builder.WithVSize("480px").WithHSize("640px").WithPosition(position)
dialog_builder.WithParameter("Property_1", "Incoming data for the property")
dialog_builder.OnComplete(lambda model: show_model_info(model))
dialog_builder.OpenDialog()
Функции для открытия sidebar в разных позициях:
def sidebar_top():
open_sidebar("Top")
def sidebar_left():
open_sidebar("Left")
def sidebar_right():
open_sidebar("Right")
def sidebar_bottom():
open_sidebar("Bottom")
context.PlatformServices.DialogBuilder
#
Функции context.PlatformServices.DialogBuilder
используются для создания модальных окон, открывающихся поверх текущего окна (формы) приложения.
Пример набора функций, которые создают и показывают модальное окно поверх текущего окна. Важно изменить ID компонента и окна (page), которые будут использоваться:
def show_model_info(model):
context.Logger.Info("show_model_info")
context.Logger.Info("Property Property_1=" + model.Data.Property_1)
def open_custom_modal():
# Creating a modal window template using the GUID of a specific component
dialog_builder = context.PlatformServices.DialogBuilder('4b7675ae-406a-45bd-9bf9-526cc78ce476')
# Setting the title for the modal window and selecting a specific page from the component's settings
# Also setting the component instance ID to 1, so the first saved instance of component data will be used
dialog_builder.WithEntryId(1).WithTitle("Open for test").WithPageId('8bd5310a-b7ff-4f65-bc38-3f4c20058483')
# Setting the size of the modal window
dialog_builder.WithVSize("480px").WithHSize("640px")
# Adding a value for the Property_1, which should be in the used component
dialog_builder.WithParameter("Property_1", "Incoming data for the property")
# Configuring the callback function for the modal window's Ok button.
# If the window is closed or the cancel button is pressed, nothing is called
dialog_builder.OnComplete(lambda model: show_model_info(model))
# Opening the created modal window
dialog_builder.OpenDialog()
context.SessionManager
#
context.SessionManager
можно использовать для получения данных о пользовательском token, а так же для принудительного выхода из сессии.
Доступные методы:
context.SessionManager.GetAccessToken()
: Получает текущий токен.context.SessionManager.UpdateToken(token)
: Обновляет токен на новый.context.SessionManager.LogOut()
: Завершает текущую сессию для пользователя (user logout).
context.Runtime
#
context.Runtime
можно использовать для вызова функций JavaScript. Void для вызова функций без возвращаемого значения. Async для асинхронного вызова.
Доступные методы:
context.Runtime.Invoke()
: Вызывает функцию.context.Runtime.InvokeVoid()
: Вызывает функцию без возвращаемого значения.context.Runtime.InvokeAsync()
: Асинхронно вызывает функцию.context.Runtime.InvokeVoidAsync()
: Асинхронно вызывает функцию без возвращаемого значения.
context.UserInfo
#
context.UserInfo
можно использовать для работы с учетной записью пользователя.
Доступные методы:
context.UserInfo.Identity()
: Получает информацию о текущем пользователе.context.UserInfo.Identities()
: Получает список всех идентификаторов пользователя.
context.ConfirmationServices
#
context.ConfirmationServices
можно использовать для открытия простых диалогов.
Доступные методы:
context.ConfirmationServices.Confirm(message, header, icon)
: Простой диалог подтверждения с указанным сообщением, заголовком и иконкой.context.ConfirmationServices.ConfirmAsync(message, header, icon)
: Простой немодальный диалог подтверждения с указанным сообщением, заголовком и иконкой.context.ConfirmationServices.StateTheReason(header)
: Простой диалог с заголовком и кнопкой ОК.
smth.Busy(boolean)
, smth.Error(boolean, string)
, smth.GetDynamicFilterValue(string)
#
Метод Busy(boolean)
переводит UIElement в статус загрузки, показывает или убирает прелоадер.
Метод Error(boolean, string)
переводит UIElement в статус ошибки, показывает сообщение об ошибке.
Метод GetDynamicFilterValue(string)
вычисляет занчение Dynamic фильтра. Если на одно поле есть два фильтра, будет вычислен первый по списку
Примеры:
def OnDataflowComplete(dataResult, dstList, srcList):
srcList.Busy(False)
dstList.Busy(False)
'''Update lists'''
srcList.Refresh()
dstList.Refresh()
def OnDataflowError(exception, dstList, srcList):
srcList.Error(True, "An error occurred")
dstList.Error(True)
context.Logger.Error(exception, "An error occurred during data-flow call")
def OnMove(dstList, srcList, dataObject, oldIdx, newIdx):
context.Logger.Info("Callback on move")
srcList.Busy(True)
dstList.Busy(True)
stage = dstList.GetDynamicFilterValue("data.Stage")
'''Creating a model to call data-flow'''
flowModel = { "Stage": stage, "OrderId": dataObject.Id }
'''Calling data-flow with new onComplete and onError overrides'''
context.ExecuteDataflow("783cf3e3-d8f8-4551-8447-13be4f738e41", flowModel,
lambda res: OnDataflowComplete(res, dstList, srcList),
lambda ex: OnDataflowError(ex, dstList, srcList))
Загрузка картинок через http.client и file storage#
Доступно только в скриптах Dataflow
:
import http.client
import file_storage
host = "docs.scalaxi.ru"
conn = http.client.HTTPSConnection(host)
conn.request("GET", "/ru/_images/main-dashboard-new.png", headers={"Host": host})
response = conn.getresponse()
'Пишем файл'
file_id = file_storage.upload_file(response.read(), "test_blob.dat")
item["uploaded_file@uuid"] = file_id
'Reading back'
data_bytes = file_storage.download_file(file_id)
SIP в Component Script#
Проверка доступности SIP: Вы можете управлять доступностью SIP, обратившись к свойству Enabled.
# SIP-телефон доступен
context.PlatformServices.SipPhone.Enabled = True
# SIP-телефон недоступен
context.PlatformServices.SipPhone.Enabled = False
Реакция на события звонков: Вы можете подписаться на различные события, такие как создание исходящего звонка, получение входящего звонка, завершение звонка и ответ на звонок.
context.PlatformServices.SipPhone.OutgoingCallCreated(lambda call_info: (
# Processing of outgoing call creation event
))
context.PlatformServices.SipPhone.CallReceived(lambda call_info: (
# Processing of incoming call reception event
))
context.PlatformServices.SipPhone.CallHangUp(lambda: (
# Processing of call termination event
))
context.PlatformServices.SipPhone.CallAnswered(lambda: (
# Processing of call answer event
))
Вызов и завершение звонка: Вы можете совершать вызов и завершать звонок с помощью следующих методов:
# Initiating a call using the entered number.
context.PlatformServices.SipPhone.Call(number)
# Ending the current call.
context.PlatformServices.SipPhone.HangUp()
Создание компонента телефона: Вы можете дополнительно создать компонент, который будет отображаться при событии звонка в рамках небольшой технической области.
phone_component_builder = context.PlatformServices.SipPhone.ShowComponent("phoneComponent")
Про его настройку можно почитать ниже.
Настройка параметров и стилей компонента: Эти методы позволяют регистрировать параметры, идентификаторы страниц и стили компонентов телефона, а также идентификаторы записей, если необходимо:
WithParameter(key, value) - Описание: Регистрирует параметр компонента;
WithPageId(pageId) - Описание: Регистрирует идентификатор страницы компонента;
WithEntryId(entryId) - Описание: Регистрирует идентификатор записи;
WithStyle(style) - Описание: Регистрирует стиль компонента;
DisplayValue() - Описание: Используется для получения информации о вызове, а именно, он выводит одно из двух полей:
DisplayName или FriendlyName, в зависимости от того, какое из них заполнено данными.
Если оба поля заполнены данными, метод может возвращать значение DisplayName, или FriendlyName,
в зависимости от логики вашего приложения;
Show() - Описание: Отображает компонент;
CloseComponent() - Описание: Используется для закрытия компонента, если есть необходимость открыть новый.
Запросы к сервису catalogs из скриптов сценариев data-flow#
Этот код использует модуль Python под названием catalogs
. В нем выполняется SQL-запрос для выборки данных из таблицы с идентификатором “f28ff85c-ddad-4704-bb80-407bc45315ab”. Запрос выбирает поля "Id"
, "Name"
и "Data_Property_1"
, где значение поля "Name"
равно определенному значению (в данном случае "test name"
). Результат выполнения запроса записывается в переменную query_result
.
import catalogs
query = catalogs.query('select \
test_cmp."Id", \
test_cmp."Name", \
test_cmp."Data_Property_1", \
test_cmp."Data_Property_1" \
from "f28ff85c-ddad-4704-bb80-407bc45315ab" as test_cmp \
where test_cmp."Name" = @test_cmp_name')
query.add_parameter("@test_cmp_name", "test name")
item["query_result"] = query.execute()
Добавление методов CRUD для скриптов сценариев data-flow#
Добавление методов CRUD для работы с сущностями: В данном коде используется библиотека catalogs
, которая предоставляет методы для работы с сущностями (entity sets). Сначала создается экземпляр сущности entity_set с указанием соответствующего идентификатора. Затем формируются операции создания, обновления и удаления записей с использованием методов create()
, update()
и delete()
соответственно. Для каждой операции устанавливаются соответствующие свойства и выполняются соответствующие команды.
import catalogs
import json_extensions
# receive an entity set
entity_set = catalogs.entity_set("9f73ef4f-ebe4-44e5-a64d-5c8a1244be92")
# create a 'create' task
create_operation = entity_set.create()
# set the name
create_operation.set_name(json_extensions.select_token(item,"data.Property_For_Name"))
# write the property value
create_operation.data["Property_For_Name"] = json_extensions.select_token(item,"data.Property_For_Name")
# enable logging
create_operation.no_tracking()
# execute the command and obtain the record ID
entry_id = create_operation.apply()
# create an 'update' task
update_operation = entity_set.update(entry_id)
# enable logging
update_operation.no_tracking()
# set the name
update_operation.set_name("нове имя")
# write the property value
update_operation.data["Property_For_Name"] = "новое значений"
# execute the command
update_operation.apply()
# create a 'delete' task
delete_operation = entity_set.delete(entry_id)
# execute the command
delete_operation.apply()
Методы расширения для работы с JSON#
В данном коде используется библиотека json_extensions
, которая предоставляет методы для работы с JSON-данными. Например, методы select_token()
и select_tokens()
используются для выбора элементов по указанному пути или запросу. Методы is_null()
и is_undefined()
используются для проверки типа элемента на значение Null или undefined соответственно.
import json_extensions
# Get the item by path
json_extensions.select_token(item,"data.Property_For_Name")
# Select items by query
json_extensions.select_tokens(item,"data.Property_For_Name <> ''")
# Check the item type for Null
json_extensions.is_null(item)
# Check the item type for undefined
json_extensions.is_undefined(item)