Использование 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 или обоих.

../_images/python-modules.png

Добавление нового модуля#

При нажатии на кнопку “Add” открывается окно добавления нового модуля.

../_images/add-python-module.png

В этом окне вы можете:

  • Выбрать тип доступности нового модуля (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)