Использование 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 phone is available
context.PlatformServices.SipPhone.Enabled = True
    # SIP phone is unavailable
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) - Description: Registers a component parameter;
WithPageId(pageId) - Description: Registers the component's page identifier;
WithEntryId(entryId) - Description: Registers the entry identifier;
WithStyle(style) - Description: Registers the component style;
DisplayValue() - Description: Used to retrieve call information, specifically, it outputs one of two fields: 
DisplayName or FriendlyName, depending on which one is populated with data. 
If both fields are populated, the method can return the value of either DisplayName or FriendlyName, 
depending on the logic of your application;
Show() - Description: Displays the component;
CloseComponent() - Description: Used to close the component if there is a need to open a new one.


Запросы к сервису 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)