Skip to content
Snippets Groups Projects
Commit cd429729 authored by Eterevskiy Georgiy's avatar Eterevskiy Georgiy
Browse files

Merge branch 'feature/AUTO-4051' into 'master'

Добавлена документация пакета perxis.extensions

See merge request perxis/perxis-python!94
parents 93beed6e 83ea8f20
No related branches found
No related tags found
No related merge requests found
"""
Модуль содержит вспомогательные функции для работы с экшнами
"""
import copy import copy
from google.protobuf.struct_pb2 import Struct from google.protobuf.struct_pb2 import Struct
...@@ -8,6 +13,18 @@ ACTIONS_COLLECTION_ID = "space_actions" ...@@ -8,6 +13,18 @@ ACTIONS_COLLECTION_ID = "space_actions"
def process_action_id(action_id: str) -> str: def process_action_id(action_id: str) -> str:
"""
Функция для преобразования идентификатора действия чтобы в дальнейшем его можно было
использовать в Servicer. Примеры преобразований:
- some-action -> some_action
- some other action -> some_other_action
Arguments:
action_id (str): идентификатор действия
Returns:
str: обработанный идентификатор действия
"""
action_id = action_id.lower().replace("-", "_").replace(" ", "_") action_id = action_id.lower().replace("-", "_").replace(" ", "_")
return action_id return action_id
...@@ -20,6 +37,18 @@ def make_action_dict( ...@@ -20,6 +37,18 @@ def make_action_dict(
kind: int, kind: int,
**kwargs, **kwargs,
) -> dict: ) -> dict:
"""
Функция для создания dict нужной структуры. В дальнейшем он идёт в свойство data item'а
Arguments:
extension_id (str): идентификатор расширения
action_id (str): идентификатор действия
name (str): название action'а
kind (str): область действия action'а согласно [документации](https://docs.perxis.ru/docs/api/extension/#actionkind)
kwargs: любые доп. параметры согласно [документации](https://docs.perxis.ru/docs/api/extension/#action)
Returns:
dict
"""
action_id = process_action_id(action_id) action_id = process_action_id(action_id)
return { return {
...@@ -32,6 +61,14 @@ def make_action_dict( ...@@ -32,6 +61,14 @@ def make_action_dict(
def make_action_struct(data: dict) -> Struct: def make_action_struct(data: dict) -> Struct:
"""
Вспомогательная функция для создания объекта Struct на основании данных из dict
Arguments:
data (dict)
Returns:
google.protobuf.struct_pb2.Struct
"""
struct = Struct() struct = Struct()
struct.update(data) struct.update(data)
...@@ -39,6 +76,18 @@ def make_action_struct(data: dict) -> Struct: ...@@ -39,6 +76,18 @@ def make_action_struct(data: dict) -> Struct:
def make_action_item(space_id: str, env_id: str, data: dict) -> items_pb2.Item: def make_action_item(space_id: str, env_id: str, data: dict) -> items_pb2.Item:
"""
Функция для создания items_pb2.Item с данными action'а
Arguments:
space_id (str): идентификатор пространства в котором будет создан action
env_id (str): идентификатор окружения в котором будет создан action
data (dict): данные action'а
Returns:
items_pb2.Item
"""
copied_data = copy.deepcopy(data) copied_data = copy.deepcopy(data)
action_id = copied_data.pop("id") action_id = copied_data.pop("id")
......
"""
Модуль содержит функцию bootstrap для упрощения запуска сервисов расширений
"""
import asyncio import asyncio
import aiocron import aiocron
...@@ -140,7 +145,33 @@ def bootstrap( ...@@ -140,7 +145,33 @@ def bootstrap(
files_host: str = "files:8003", files_host: str = "files:8003",
images_host: str = "images:8005" images_host: str = "images:8005"
): ):
"""
Функция для инициализации и запуска сервиса расширения.
Пример использования в расширении:
```
def main():
ext_descriptor = utils.get_extension_descriptor(
ext_host="demo-ext-backend:50051",
ext_id=extension.ID,
ext_name=extension.NAME,
ext_version=extension.VERSION,
ext_description=extension.DESCRIPTION,
ext_version_description=extension.VERSION_DESCRIPTION
)
bootstrap(ext_descriptor, Servicer, ext_manager_host, content_host)
```
Arguments:
ext_descriptor (manager_service_pb2.ExtensionDescriptor): Дескриптор расширения
servicer_cls (extension_service_pb2_grpc.ExtensionServiceServicer): класс (не экземпляр!) сервиса
ext_manager_host (str): адрес сервиса менеджера расширений
content_host (str): адрес сервиса контента
account_host (str): адрес сервиса аккаунтов
files_host (str): адрес сервиса файлов
images_host (str): адрес сервиса работы с изображениями
"""
logger.info(f"Инициализация сервиса расширения {ext_descriptor.extension}") logger.info(f"Инициализация сервиса расширения {ext_descriptor.extension}")
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
......
This diff is collapsed.
"""
Модуль содержит класс ExtensionSetup. Он используется для управления всеми данными расширения
"""
import logging import logging
import grpc import grpc
...@@ -24,6 +29,22 @@ logger = logging.getLogger(__name__) ...@@ -24,6 +29,22 @@ logger = logging.getLogger(__name__)
class ExtensionSetup: class ExtensionSetup:
"""
Attributes:
collections_service (collections_pb2_grpc.CollectionsStub): ссылка на сервис коллекций
environments_service (environments_pb2_grpc.EnvironmentsStub): ссылка на сервис окружений
roles_service (roles_pb2_grpc.RolesStub): ссылка на сервис ролей
clients_service (clients_pb2_grpc.ClientsStub): ссылка на сервис клиентов
items_service (items_pb2_grpc.ItemsStub): ссылка на сервис item'ов
collections (list[collections_pb2.Collection]): список коллекций расширения
clients (list[clients_pb2.Client]): список клиентов расширения
roles (list[roles_pb2.Role]): список ролей расширения
items (list[AbstractItem]): список item'ов расширения
__max_attempts_count (int): макс. кол-во попыток записи
__sleep_time (int): время ожидания перед попыткой
"""
def __init__( def __init__(
self, self,
collections_service: collections_pb2_grpc.CollectionsStub, collections_service: collections_pb2_grpc.CollectionsStub,
...@@ -76,6 +97,16 @@ class ExtensionSetup: ...@@ -76,6 +97,16 @@ class ExtensionSetup:
# Работа с ролями # Работа с ролями
async def __remove_roles(self, space_id: str) -> list[str]: async def __remove_roles(self, space_id: str) -> list[str]:
"""
Метод для удаления ролей из пространства. Возвращает массив с ошибками
Arguments:
space_id (str): идентификатор пространства
Returns:
list[str]
"""
errors_list: list[str] = [] errors_list: list[str] = []
for role in self.roles: for role in self.roles:
...@@ -93,6 +124,16 @@ class ExtensionSetup: ...@@ -93,6 +124,16 @@ class ExtensionSetup:
return errors_list return errors_list
async def __check_roles(self, space_id: str) -> list[str]: async def __check_roles(self, space_id: str) -> list[str]:
"""
Метод для проверки ролей из пространства. Возвращает массив с ошибками
Arguments:
space_id (str): идентификатор пространства
Returns:
list[str]
"""
errors_list = [] errors_list = []
for role in self.roles: for role in self.roles:
...@@ -106,6 +147,18 @@ class ExtensionSetup: ...@@ -106,6 +147,18 @@ class ExtensionSetup:
return errors_list return errors_list
async def __update_roles(self, space_id: str, env_id: str) -> list[str]: async def __update_roles(self, space_id: str, env_id: str) -> list[str]:
"""
Метод для установки ролей в пространство. Возвращает массив с ошибками. Права доступа
которые были установлены в perxis вручную или другим расширением не затираются.
Arguments:
space_id (str): идентификатор пространства
env_id (str): идентификатор окружения
Returns:
list[str]
"""
errors_list = [] errors_list = []
for local_role in self.roles: for local_role in self.roles:
...@@ -186,6 +239,16 @@ class ExtensionSetup: ...@@ -186,6 +239,16 @@ class ExtensionSetup:
# Работа с клиентами # Работа с клиентами
async def __check_clients(self, space_id: str) -> list[str]: async def __check_clients(self, space_id: str) -> list[str]:
"""
Метод для проверки клиентов в пространстве. Возвращает массив с ошибками
Arguments:
space_id (str): идентификатор пространства
Returns:
list[str]
"""
errors_list = [] errors_list = []
for client in self.clients: for client in self.clients:
...@@ -199,6 +262,16 @@ class ExtensionSetup: ...@@ -199,6 +262,16 @@ class ExtensionSetup:
return errors_list return errors_list
async def __remove_clients(self, space_id: str) -> list[str]: async def __remove_clients(self, space_id: str) -> list[str]:
"""
Метод для удаления клиентов из пространства. Возвращает массив с ошибками
Arguments:
space_id (str): идентификатор пространства
Returns:
list[str]
"""
errors_list: list[str] = [] errors_list: list[str] = []
for client in self.clients: for client in self.clients:
...@@ -216,6 +289,17 @@ class ExtensionSetup: ...@@ -216,6 +289,17 @@ class ExtensionSetup:
return errors_list return errors_list
async def __update_clients(self, space_id: str) -> list[str]: async def __update_clients(self, space_id: str) -> list[str]:
"""
Метод для создания / обновления клиентов в пространстве. Возвращает массив с ошибками.
Свойства oauth и api_key не затираются в случае если клиент уже был создан
Arguments:
space_id (str): идентификатор пространства
Returns:
list[str]
"""
errors_list = [] errors_list = []
for local_client in self.clients: for local_client in self.clients:
...@@ -278,6 +362,17 @@ class ExtensionSetup: ...@@ -278,6 +362,17 @@ class ExtensionSetup:
# Работа с коллекциями # Работа с коллекциями
async def __remove_collections(self, space_id: str, env_id: str) -> list[str]: async def __remove_collections(self, space_id: str, env_id: str) -> list[str]:
"""
Метод для удаления коллекций из определённого окружения пространства. Возвращает массив с ошибками
Arguments:
space_id (str): идентификатор пространства
env_id (str): идентификатор окружения
Returns:
list[str]
"""
errors_list: list[str] = [] errors_list: list[str] = []
for collection in self.collections: for collection in self.collections:
...@@ -295,6 +390,17 @@ class ExtensionSetup: ...@@ -295,6 +390,17 @@ class ExtensionSetup:
return errors_list return errors_list
async def __check_collections(self, space_id: str, env_id: str) -> list[str]: async def __check_collections(self, space_id: str, env_id: str) -> list[str]:
"""
Метод для проверки коллекций из определённого окружения пространства. Возвращает массив с ошибками
Arguments:
space_id (str): идентификатор пространства
env_id (str): идентификатор окружения
Returns:
list[str]
"""
errors_list = [] errors_list = []
for collection in self.collections: for collection in self.collections:
...@@ -316,6 +422,13 @@ class ExtensionSetup: ...@@ -316,6 +422,13 @@ class ExtensionSetup:
3. Сравнить схему коллекции в расширении и в perxis 3. Сравнить схему коллекции в расширении и в perxis
4. Если схема изменена - обновить схему в perxis 4. Если схема изменена - обновить схему в perxis
5. Если обновлялась хотя бы одна схема в perxis - запустить миграцию окружения 5. Если обновлялась хотя бы одна схема в perxis - запустить миграцию окружения
Arguments:
space_id (str): идентификатор пространства
env_id (str): идентификатор окружения
Returns:
list[str]
""" """
need_to_migrate_environment = False need_to_migrate_environment = False
...@@ -388,8 +501,17 @@ class ExtensionSetup: ...@@ -388,8 +501,17 @@ class ExtensionSetup:
return errors_list return errors_list
async def __migrate_environment(self, space_id: str, env_id: str) -> typing.Optional[str]: async def __migrate_environment(self, space_id: str, env_id: str) -> typing.Optional[str]:
# Так как perxis может не сразу выставить коллекции / окружению статус ready операцию необходимо выполнять """
# с попытками Метод для миграции окружения.
Так как perxis может не сразу выставить коллекции / окружению статус ready операцию необходимо выполнять
с попытками
Arguments:
space_id (str): идентификатор пространства
env_id (str): идентификатор окружения
Returns:
str | None
"""
attempt = 0 attempt = 0
is_ok = False is_ok = False
...@@ -421,8 +543,19 @@ class ExtensionSetup: ...@@ -421,8 +543,19 @@ class ExtensionSetup:
return error_message return error_message
async def __set_collection_schema(self, space_id: str, env_id: str, collection_id: str, schema: str) -> typing.Optional[str]: async def __set_collection_schema(self, space_id: str, env_id: str, collection_id: str, schema: str) -> typing.Optional[str]:
# Так как perxis может не сразу выставить коллекции / окружению статус ready операцию необходимо выполнять """
# с попытками Метод для установки схемы коллекции в определённом окружении пространства
Так как perxis может не сразу выставить коллекции / окружению статус ready операцию необходимо выполнять
с попытками
Arguments:
space_id (str): идентификатор пространства
env_id (str): идентификатор окружения
collection_id (str): идентификатор коллекции
schema (str): схема коллекции в формате json
Returns:
str | None
"""
attempt = 0 attempt = 0
is_ok = False is_ok = False
...@@ -456,6 +589,17 @@ class ExtensionSetup: ...@@ -456,6 +589,17 @@ class ExtensionSetup:
# Работа с действиями # Работа с действиями
async def __check_actions(self, space_id: str, env_id: str) -> list[str]: async def __check_actions(self, space_id: str, env_id: str) -> list[str]:
"""
Метод для проверки действий из определённого окружения пространства. Возвращает массив с ошибками
Arguments:
space_id (str): идентификатор пространства
env_id (str): идентификатор окружения
Returns:
list[str]
"""
errors_list = [] errors_list = []
ids = [data["id"] for data in self.actions if data.get("id")] ids = [data["id"] for data in self.actions if data.get("id")]
...@@ -490,6 +634,17 @@ class ExtensionSetup: ...@@ -490,6 +634,17 @@ class ExtensionSetup:
return errors_list return errors_list
async def __update_actions(self, space_id: str, env_id: str) -> list[str]: async def __update_actions(self, space_id: str, env_id: str) -> list[str]:
"""
Метод для создания / обновления действий из определённого окружения пространства. Возвращает массив с ошибками
Arguments:
space_id (str): идентификатор пространства
env_id (str): идентификатор окружения
Returns:
list[str]
"""
errors_list = [] errors_list = []
not_found = False not_found = False
...@@ -549,6 +704,17 @@ class ExtensionSetup: ...@@ -549,6 +704,17 @@ class ExtensionSetup:
return errors_list return errors_list
async def __remove_actions(self, space_id: str, env_id: str) -> list[str]: async def __remove_actions(self, space_id: str, env_id: str) -> list[str]:
"""
Метод для удаления действий из определённого окружения пространства. Возвращает массив с ошибками
Arguments:
space_id (str): идентификатор пространства
env_id (str): идентификатор окружения
Returns:
list[str]
"""
errors_list = [] errors_list = []
for action in self.actions: for action in self.actions:
action_item = make_action_item(space_id, env_id, action) action_item = make_action_item(space_id, env_id, action)
...@@ -578,6 +744,17 @@ class ExtensionSetup: ...@@ -578,6 +744,17 @@ class ExtensionSetup:
return errors_list return errors_list
async def __check_items(self, space_id: str, env_id: str) -> list[str]: async def __check_items(self, space_id: str, env_id: str) -> list[str]:
"""
Метод для item'ов действий из определённого окружения пространства. Возвращает массив с ошибками
Arguments:
space_id (str): идентификатор пространства
env_id (str): идентификатор окружения
Returns:
list[str]
"""
errors_list: list[str] = [] errors_list: list[str] = []
wrapper = PerxisItemsWrapper( wrapper = PerxisItemsWrapper(
self.items_service, self.items_service,
...@@ -611,6 +788,17 @@ class ExtensionSetup: ...@@ -611,6 +788,17 @@ class ExtensionSetup:
return errors_list return errors_list
async def __update_items(self, space_id: str, env_id: str) -> list[str]: async def __update_items(self, space_id: str, env_id: str) -> list[str]:
"""
Метод для создания / обновления item'ов из определённого окружения пространства. Возвращает массив с ошибками
Arguments:
space_id (str): идентификатор пространства
env_id (str): идентификатор окружения
Returns:
list[str]
"""
errors_list: list[str] = [] errors_list: list[str] = []
wrapper = PerxisItemsWrapper( wrapper = PerxisItemsWrapper(
self.items_service, self.items_service,
...@@ -694,6 +882,17 @@ class ExtensionSetup: ...@@ -694,6 +882,17 @@ class ExtensionSetup:
return errors_list return errors_list
async def __remove_items(self, space_id: str, env_id: str) -> list[str]: async def __remove_items(self, space_id: str, env_id: str) -> list[str]:
"""
Метод для удаления item'ов из определённого окружения пространства. Возвращает массив с ошибками
Arguments:
space_id (str): идентификатор пространства
env_id (str): идентификатор окружения
Returns:
list[str]
"""
errors_list: list[str] = [] errors_list: list[str] = []
wrapper = PerxisItemsWrapper( wrapper = PerxisItemsWrapper(
self.items_service, self.items_service,
...@@ -742,6 +941,17 @@ class ExtensionSetup: ...@@ -742,6 +941,17 @@ class ExtensionSetup:
return errors_list return errors_list
async def __update_view_role(self, space_id: str, env_id: str, mode: str = "add") -> list[str]: async def __update_view_role(self, space_id: str, env_id: str, mode: str = "add") -> list[str]:
"""
Метод для создания / обновления роли view из определённого окружения пространства. Возвращает массив с ошибками
Arguments:
space_id (str): идентификатор пространства
env_id (str): идентификатор окружения
Returns:
list[str]
"""
errors = [] errors = []
# Нужны только относящиеся к синхронизации элементы # Нужны только относящиеся к синхронизации элементы
...@@ -850,6 +1060,20 @@ class ExtensionSetup: ...@@ -850,6 +1060,20 @@ class ExtensionSetup:
async def install(self, space_id: str, env_id: str, use_force: bool) -> list[str]: async def install(self, space_id: str, env_id: str, use_force: bool) -> list[str]:
"""
Метод установки расширения.
TODO разобраться нужны ли отдельные методы `install` и `update`
TODO разобраться с аргументом `use_force`
Arguments:
space_id (str): идентификатор пространства
env_id (str): идентификатор окружения
use_force (bool): флаг не используется
Returns:
list[str]
"""
errors = [] errors = []
try: try:
...@@ -866,6 +1090,20 @@ class ExtensionSetup: ...@@ -866,6 +1090,20 @@ class ExtensionSetup:
return errors return errors
async def update(self, space_id: str, env_id: str, use_force: bool) -> list[str]: async def update(self, space_id: str, env_id: str, use_force: bool) -> list[str]:
"""
Метод установки расширения.
TODO разобраться нужны ли отдельные методы `install` и `update`
TODO разобраться с аргументом `use_force`
Arguments:
space_id (str): идентификатор пространства
env_id (str): идентификатор окружения
use_force (bool): флаг не используется
Returns:
list[str]
"""
errors = [] errors = []
try: try:
...@@ -882,6 +1120,17 @@ class ExtensionSetup: ...@@ -882,6 +1120,17 @@ class ExtensionSetup:
return errors return errors
async def check(self, space_id: str, env_id: str) -> list[str]: async def check(self, space_id: str, env_id: str) -> list[str]:
"""
Метод проверки расширения.
Arguments:
space_id (str): идентификатор пространства
env_id (str): идентификатор окружения
Returns:
list[str]
"""
errors = [] errors = []
try: try:
...@@ -897,6 +1146,18 @@ class ExtensionSetup: ...@@ -897,6 +1146,18 @@ class ExtensionSetup:
return errors return errors
async def uninstall(self, space_id: str, env_id: str, use_remove: bool) -> list[str]: async def uninstall(self, space_id: str, env_id: str, use_remove: bool) -> list[str]:
"""
Метод удаления расширения.
Arguments:
space_id (str): идентификатор пространства
env_id (str): идентификатор окружения
use_remove (str): удалять данные расширения
Returns:
list[str]
"""
errors = [] errors = []
if use_remove: if use_remove:
try: try:
......
"""
Модуль содержит классы для работы с item'ами в расширениях
"""
import abc import abc
from typing import TypedDict, NotRequired from typing import TypedDict, NotRequired
...@@ -7,6 +12,9 @@ from perxis.extensions.item_rules import AbstractRule, IfCollectionExists, IfExt ...@@ -7,6 +12,9 @@ from perxis.extensions.item_rules import AbstractRule, IfCollectionExists, IfExt
class DataSourceData(TypedDict): class DataSourceData(TypedDict):
"""
Маппинг для объекта data элементов коллекции web_datasources
"""
query: NotRequired[str] query: NotRequired[str]
content_type: NotRequired[str] content_type: NotRequired[str]
exclude: NotRequired[bool] exclude: NotRequired[bool]
...@@ -15,6 +23,10 @@ class DataSourceData(TypedDict): ...@@ -15,6 +23,10 @@ class DataSourceData(TypedDict):
class SyncPolicyData(TypedDict): class SyncPolicyData(TypedDict):
"""
Маппинг для объекта data элементов коллекции hoop_item_sync_policies
"""
key: NotRequired[str] key: NotRequired[str]
export_view: NotRequired[bool] export_view: NotRequired[bool]
remove_collection: NotRequired[bool] remove_collection: NotRequired[bool]
...@@ -31,6 +43,16 @@ class AbstractItem(metaclass=abc.ABCMeta): ...@@ -31,6 +43,16 @@ class AbstractItem(metaclass=abc.ABCMeta):
""" """
Абстрактный класс для item'а. Нужен для определения общих свойств без реализации какого Абстрактный класс для item'а. Нужен для определения общих свойств без реализации какого
то конкретного конструктора. то конкретного конструктора.
Attributes:
collection_id (str): идентификатор коллекции
data (dict): данные item'а
rules (list[AbstractRule]): список правил применения item'а
identifier_field (str): поле по которому будет производиться поиск элемента в perxis
with_update (bool): указание возможности обновления элемента при установке или удалении расширения
в случае если он уже существует в perxis
with_delete (bool): указание возможности удаления элемента в случае если он существует в perxis при
удалении расширения
""" """
collection_id: str collection_id: str
...@@ -43,16 +65,40 @@ class AbstractItem(metaclass=abc.ABCMeta): ...@@ -43,16 +65,40 @@ class AbstractItem(metaclass=abc.ABCMeta):
@property @property
def identifier(self): def identifier(self):
"""
Метод для получения значения идентификатора элемента из данных
Returns:
str
"""
return self.data[self.identifier_field] return self.data[self.identifier_field]
@property @property
def struct(self) -> Struct: def struct(self) -> Struct:
"""
Метод для преобразования данных элемента из dict в Struct
Returns:
Struct
"""
s = Struct() s = Struct()
s.update(self.data) s.update(self.data)
return s return s
async def all_rules_is_satisfied(self, space_id: str, env_id: str) -> bool: async def all_rules_is_satisfied(self, space_id: str, env_id: str) -> bool:
"""
Метод для проверки применимости всех правил item'а для указанных пространства и окружения.
Возвращает True в случае если все указанные для item'а правила вернули True
Arguments:
space_id (str): идентификатор пространства
env_id (str): идентификатор окружения
Returns:
bool
"""
return all( return all(
[ [
await rule(item=self, space_id=space_id, env_id=env_id) await rule(item=self, space_id=space_id, env_id=env_id)
...@@ -63,8 +109,32 @@ class AbstractItem(metaclass=abc.ABCMeta): ...@@ -63,8 +109,32 @@ class AbstractItem(metaclass=abc.ABCMeta):
def merge_data(self, data_from_perxis: dict) -> Struct: def merge_data(self, data_from_perxis: dict) -> Struct:
""" """
Мерж данных из перксиса и расширения. В приоритете данные расширения, если что-то Метод для слияния данных из perxis и расширения. Нужен для того чтобы не затирать те поля
что были заполнены в базе данных но отсутствуют в item'е расширения. В приоритете данные расширения, если что-то
из них было вручную изменено в perxis - значение будет затёрто из них было вручную изменено в perxis - значение будет затёрто
Пример.
```
# Данные в perxis
{
"a": 1,
"b": 2,
"c": 3,
}
# Данные в расширении
{
"b": 1,
"c": 3,
}
# Итоговый результат
{
"a": 1,
"b": 1,
"c": 3,
}
```
""" """
s = Struct() s = Struct()
...@@ -90,6 +160,18 @@ class Item(AbstractItem): ...@@ -90,6 +160,18 @@ class Item(AbstractItem):
identifier_field: str = "id", identifier_field: str = "id",
rules: list[AbstractRule] | None = None rules: list[AbstractRule] | None = None
): ):
"""
Arguments:
collection_id (str): идентификатор коллекции
data (dict): данные item'а
with_update (bool): указание возможности обновления элемента при установке или удалении расширения
в случае если он уже существует в perxis
with_delete (bool): указание возможности удаления элемента в случае если он существует в perxis при
удалении расширения
rules (list[AbstractRule]): список правил применения item'а
identifier_field (str): поле по которому будет производиться поиск элемента в perxis
"""
self.collection_id = collection_id self.collection_id = collection_id
self.data = data self.data = data
self.identifier_field = identifier_field self.identifier_field = identifier_field
...@@ -100,7 +182,8 @@ class Item(AbstractItem): ...@@ -100,7 +182,8 @@ class Item(AbstractItem):
class DataSourceItem(AbstractItem): class DataSourceItem(AbstractItem):
""" """
Класс для системной коллекции web_datasources Класс для системной коллекции web_datasources. По умолчанию имеет указание проверки
наличия коллекции в rules
""" """
def __init__( def __init__(
...@@ -113,6 +196,19 @@ class DataSourceItem(AbstractItem): ...@@ -113,6 +196,19 @@ class DataSourceItem(AbstractItem):
with_update: bool = True, with_update: bool = True,
with_delete: bool = True, with_delete: bool = True,
): ):
"""
Arguments:
collection_id (str): Идентификатор коллекции для выгрузки данных
query (str): Фильтр по данным
content_type (str): Настройки типа данных
exclude (bool): Не выгружать источник в каталог данных
with_update (bool): указание возможности обновления элемента при установке или удалении расширения
в случае если он уже существует в perxis
with_delete (bool): указание возможности удаления элемента в случае если он существует в perxis при
удалении расширения
rules (list[AbstractRule]): список правил применения item'а
"""
self.collection_id = "web_datasources" self.collection_id = "web_datasources"
self.rules = rules or [IfCollectionExists()] self.rules = rules or [IfCollectionExists()]
self.data = { self.data = {
...@@ -129,7 +225,9 @@ class DataSourceItem(AbstractItem): ...@@ -129,7 +225,9 @@ class DataSourceItem(AbstractItem):
class SyncPolicyItem(AbstractItem): class SyncPolicyItem(AbstractItem):
""" """
Класс для коллекции hoop_item_sync_policies расширения perxishoop Класс для коллекции hoop_item_sync_policies расширения perxishoop. По умолчанию item имеет
правило для проверки установленного расширения perxishoop. В качестве идентификатора записи
используется поле `collection`
""" """
identifier_field = "collection" identifier_field = "collection"
...@@ -149,6 +247,26 @@ class SyncPolicyItem(AbstractItem): ...@@ -149,6 +247,26 @@ class SyncPolicyItem(AbstractItem):
with_update: bool = False, with_update: bool = False,
with_delete: bool = False, with_delete: bool = False,
): ):
"""
Arguments:
collection_id (str): Идентификатор коллекции для выгрузки данных
name (str): Название
key (str): Ключ для синхронизации
export_view (bool): Создать отображение коллекции
remove_collection (bool): Удалить коллекцию
deny_publish (bool): Запретить операции с публикацией элементов ведущего пространства
deny_delete (bool): Запретить удаление элементов ведущего пространства
deny_create (bool): Запретить создавать новые элементы
deny_read (bool): Запретить чтение элементов
hidden (bool): Скрыть коллекцию
with_update (bool): указание возможности обновления элемента при установке или удалении расширения
в случае если он уже существует в perxis
with_delete (bool): указание возможности удаления элемента в случае если он существует в perxis при
удалении расширения
rules (list[AbstractRule]): список правил применения item'а
"""
self.collection_id = "hoop_item_sync_policies" self.collection_id = "hoop_item_sync_policies"
self.rules = rules or [IfExtensionInstalled("perxishoop")] self.rules = rules or [IfExtensionInstalled("perxishoop")]
......
...@@ -25,20 +25,39 @@ class AbstractRule(metaclass=abc.ABCMeta): ...@@ -25,20 +25,39 @@ class AbstractRule(metaclass=abc.ABCMeta):
не был излишне длинным - это делается неявным пробросом свойств из ExtensionService. Таким не был излишне длинным - это делается неявным пробросом свойств из ExtensionService. Таким
образом и код короче получается, и в случае если будут добавлены какие то новые сервисы они образом и код короче получается, и в случае если будут добавлены какие то новые сервисы они
автоматически будут проброшены сюда. автоматически будут проброшены сюда.
Attributes:
channel (grpc.Channel): ссылка на grpc канал
*_service: ссылки на сервисы. Именование аналогично тому как они указаны в классе ExtensionService
""" """
@property @property
def rule_name(self): def rule_name(self):
"""
Название правила
Returns:
str
"""
return self.__class__.__name__ return self.__class__.__name__
@property @property
def logger(self): def logger(self):
"""
Логгер для правила
Returns:
logging.Logger
"""
return logging.getLogger(self.rule_name) return logging.getLogger(self.rule_name)
def bind_services(self, service_list: list[tuple[str, object]]): def bind_services(self, service_list: list[tuple[str, object]]):
""" """
Нужно для автоматического подключения сервисов из ExtensionService. Проблема Нужно для автоматического подключения сервисов из ExtensionService. Проблема
в том что их очень много и если руками явно указывать - будет большой boilerplate в том что их очень много и если руками явно указывать - будет большой boilerplate
Arguments:
service_list (list[tuple[str, object]]): список доступных сервисов и их идентифиакторы
""" """
for service_name, service in service_list: for service_name, service in service_list:
...@@ -46,6 +65,16 @@ class AbstractRule(metaclass=abc.ABCMeta): ...@@ -46,6 +65,16 @@ class AbstractRule(metaclass=abc.ABCMeta):
@abc.abstractmethod @abc.abstractmethod
async def act(self, item: "AbstractItem", space_id: str, env_id: str): async def act(self, item: "AbstractItem", space_id: str, env_id: str):
"""
Абстрактный метод для указания логики правила. Обработка исключений ведётся в методе __call__,
уровнем выше. Если метод `act` отработал без исключений считается что правило успешно применено
Arguments:
item (AbstractItem): item с которым будет вестись работа
space_id (str): идентификатор пространства
env_id (str): идентификатор окружения
"""
raise NotImplementedError() raise NotImplementedError()
async def __call__(self, item: "AbstractItem", space_id: str, env_id: str) -> bool: async def __call__(self, item: "AbstractItem", space_id: str, env_id: str) -> bool:
...@@ -71,6 +100,15 @@ class IfCollectionExists(AbstractRule): ...@@ -71,6 +100,15 @@ class IfCollectionExists(AbstractRule):
""" """
async def act(self, item: "AbstractItem", space_id: str, env_id: str): async def act(self, item: "AbstractItem", space_id: str, env_id: str):
"""
Проверка наличия коллекции в perxis для указанного пространства и окружения
Arguments:
item (AbstractItem): item с которым будет вестись работа
space_id (str): идентификатор пространства
env_id (str): идентификатор окружения
"""
message = await self.collections_service.Get( message = await self.collections_service.Get(
collections_pb2.GetRequest( collections_pb2.GetRequest(
space_id=space_id, space_id=space_id,
...@@ -92,9 +130,22 @@ class IfExtensionInstalled(AbstractRule): ...@@ -92,9 +130,22 @@ class IfExtensionInstalled(AbstractRule):
required_extension: str required_extension: str
def __init__(self, required_extension: str): def __init__(self, required_extension: str):
"""
Arguments:
required_extension (str): Идентификатор требуемоого расширения
"""
self.required_extension = required_extension self.required_extension = required_extension
async def act(self, item: "AbstractItem", space_id: str, env_id: str): async def act(self, item: "AbstractItem", space_id: str, env_id: str):
"""
Проверка наличия установленного расширения в perxis для указанного пространства и окружения
Arguments:
item (AbstractItem): item с которым будет вестись работа
space_id (str): идентификатор пространства
env_id (str): идентификатор окружения
"""
registered_extensions = await self.ext_manager_service.ListRegisteredExtensions( registered_extensions = await self.ext_manager_service.ListRegisteredExtensions(
manager_service_pb2.ListRegisteredExtensionsRequest() manager_service_pb2.ListRegisteredExtensionsRequest()
) )
......
"""
Модуль содержит вспомогательные функции для сервисов расширений
"""
from typing import Optional from typing import Optional
from perxis.extensions import manager_service_pb2 from perxis.extensions import manager_service_pb2
...@@ -14,7 +18,7 @@ def datasource_items_from_collections( ...@@ -14,7 +18,7 @@ def datasource_items_from_collections(
""" """
Создание записей источников данных на базе маппинга коллекций. Создание записей источников данных на базе маппинга коллекций.
Args: Arguments:
collections_map: Dict вида [collection_id, collection_name] collections_map: Dict вида [collection_id, collection_name]
datasource_data: Dict со структурой DataSourceData для item'ов коллекций datasource_data: Dict со структурой DataSourceData для item'ов коллекций
override_for_collections: Dict для переопределения значений для отдельных коллекций override_for_collections: Dict для переопределения значений для отдельных коллекций
...@@ -58,7 +62,7 @@ def sync_policies_from_collections( ...@@ -58,7 +62,7 @@ def sync_policies_from_collections(
""" """
Создание записей синхронизации коллекций на базе маппинга коллекций Создание записей синхронизации коллекций на базе маппинга коллекций
Args: Arguments:
collections_map: Dict вида [collection_id, collection_name] collections_map: Dict вида [collection_id, collection_name]
sync_policies_data: Dict со структурой SyncPolicyData для item'ов коллекций sync_policies_data: Dict со структурой SyncPolicyData для item'ов коллекций
override_for_collections: Dict для переопределения значений для отдельных коллекций override_for_collections: Dict для переопределения значений для отдельных коллекций
...@@ -98,6 +102,21 @@ def get_extension_descriptor( ...@@ -98,6 +102,21 @@ def get_extension_descriptor(
ext_version: str, ext_version_description: str, ext_version: str, ext_version_description: str,
ext_deps: Optional[list[str]] = None ext_deps: Optional[list[str]] = None
) -> manager_service_pb2.ExtensionDescriptor: ) -> manager_service_pb2.ExtensionDescriptor:
"""
Функция для получения дескриптора расширения на основании его данных
Arguments:
ext_host (str): адрес расширения
ext_id (str): идентификатор расширения
ext_name (str): название расширения
ext_version (str): версия расширения
ext_version_description (str): описание расширения
ext_deps (list[str] | None): зависимости расширения
Returns:
manager_service_pb2.ExtensionDescriptor
"""
if not ext_deps: if not ext_deps:
ext_deps = [] ext_deps = []
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment