From f18d0d8b74ec958c29452fe45581019880263b88 Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Fri, 6 Sep 2024 11:53:35 +0200 Subject: [PATCH 1/2] [procedures] Recursive serialization in `procedures.to_yaml`. --- platypush/plugins/procedures/__init__.py | 37 ++++++++++++++++++++---- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/platypush/plugins/procedures/__init__.py b/platypush/plugins/procedures/__init__.py index 7bea727bc2..db3d142710 100644 --- a/platypush/plugins/procedures/__init__.py +++ b/platypush/plugins/procedures/__init__.py @@ -4,7 +4,16 @@ from contextlib import contextmanager from dataclasses import dataclass from multiprocessing import RLock from random import randint -from typing import Callable, Collection, Generator, Iterable, Optional, Union +from typing import ( + Callable, + Collection, + Dict, + Generator, + Iterable, + List, + Optional, + Union, +) import yaml from sqlalchemy.orm import Session @@ -263,11 +272,7 @@ class ProceduresPlugin(RunnablePlugin, ProcedureEntityManager): proc = { f'procedure.{name}' + (f'({", ".join(args)})' if args else ''): [ - { - 'action': action['action'], - **({'args': action['args']} if action.get('args') else {}), - } - for action in actions + self._serialize_action(action) for action in actions ] } else: @@ -281,6 +286,26 @@ class ProceduresPlugin(RunnablePlugin, ProcedureEntityManager): def _normalize_name(name: Optional[str]) -> str: return re.sub(r'[^\w.]+', '_', (name or '').strip(' .')) + @classmethod + def _serialize_action(cls, data: Union[Iterable, Dict]) -> Union[Dict, List]: + if isinstance(data, dict): + if data.get('action'): + return { + 'action': data['action'], + **({'args': data['args']} if data.get('args') else {}), + } + + return { + k: ( + cls._serialize_action(v) + if isinstance(v, (dict, list, tuple)) + else v + ) + for k, v in data.items() + } + else: + return [cls._serialize_action(item) for item in data if item is not None] + @contextmanager def _db_session(self) -> Generator[Session, None, None]: db: Optional[DbPlugin] = get_plugin(DbPlugin) From 05b1fcd43a1c0a2429683d3bf77d8f7faf1d4119 Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Fri, 6 Sep 2024 11:55:03 +0200 Subject: [PATCH 2/2] [procedures] Don't validate the presence of the `actions` field in `procedures.save`. When saving procedures with if/else/for blocks, some blocks aren't supposed to have the `actions` field. --- platypush/plugins/procedures/__init__.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/platypush/plugins/procedures/__init__.py b/platypush/plugins/procedures/__init__.py index db3d142710..3e66f7631e 100644 --- a/platypush/plugins/procedures/__init__.py +++ b/platypush/plugins/procedures/__init__.py @@ -185,9 +185,6 @@ class ProceduresPlugin(RunnablePlugin, ProcedureEntityManager): """ assert name, 'Procedure name cannot be empty' assert actions, 'Procedure actions cannot be empty' - assert all( - isinstance(action, dict) and action.get('action') for action in actions - ), 'Procedure actions should be dictionaries with an "action" key' args = args or [] proc_def = self._all_procedures.get(name, {})