diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml index ef3c5cad..04dfd177 100644 --- a/.github/workflows/tox.yml +++ b/.github/workflows/tox.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-20.04 strategy: matrix: - python-version: ["3.6", "3.8"] + python-version: ["3.6.15", "3.8.17"] steps: - name: Checkout repository uses: actions/checkout@v2 diff --git a/orquesta/expressions/functions/workflow.py b/orquesta/expressions/functions/workflow.py index e1a173bc..18149e2f 100644 --- a/orquesta/expressions/functions/workflow.py +++ b/orquesta/expressions/functions/workflow.py @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -import collections +import collections.abc from orquesta import constants from orquesta import exceptions as exc diff --git a/orquesta/expressions/jinja.py b/orquesta/expressions/jinja.py index 0cabe91c..83410b52 100644 --- a/orquesta/expressions/jinja.py +++ b/orquesta/expressions/jinja.py @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import collections.abc import functools import inspect import itertools @@ -215,6 +216,11 @@ def evaluate(cls, text, data=None): # Recursively evaluate the expression. output = cls._evaluate_and_expand(text, data=data) + # Fix #247 by casting dict_keys objects to list. Jinja returns + # dict_keys objects from dictionary .keys() method. + if isinstance(output, collections.abc.KeysView): + output = list(output) + if isinstance(output, str): exprs = [cls.strip_delimiter(expr) for expr in cls._regex_parser.findall(output)] diff --git a/orquesta/expressions/yql.py b/orquesta/expressions/yql.py index 82d40f49..e82f6c66 100644 --- a/orquesta/expressions/yql.py +++ b/orquesta/expressions/yql.py @@ -141,7 +141,9 @@ def evaluate(cls, text, data=None): stripped = cls.strip_delimiter(expr) result = cls._engine(stripped).evaluate(context=ctx) - if inspect.isgenerator(result): + # Fix #247 by casting set objects to list. YAQL returns + # set objects from dictionary .keys() method. + if inspect.isgenerator(result) or isinstance(result, set): result = list(result) if isinstance(result, str): diff --git a/orquesta/specs/base.py b/orquesta/specs/base.py index ff297c17..0161a43d 100644 --- a/orquesta/specs/base.py +++ b/orquesta/specs/base.py @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -import collections +import collections.abc import inspect import json import jsonschema diff --git a/orquesta/tests/unit/base.py b/orquesta/tests/unit/base.py index 9557b07e..51bbc55c 100644 --- a/orquesta/tests/unit/base.py +++ b/orquesta/tests/unit/base.py @@ -71,7 +71,7 @@ def assert_graph_equal(self, wf_graph, expected_wf_graph): self.assertListEqual(wf_graph_attrs, expected_wf_graph_attrs) -class WorkflowSpecTest(unittest.TestCase): +class WorkflowSpecTest(unittest.TestCase, metaclass=abc.ABCMeta): spec_module_name = "mock" def __init__(self, *args, **kwargs): @@ -141,7 +141,7 @@ def assert_compose_to_wf_ex_graph(self, wf_name, expected_wf_ex_graph): self.assert_graph_equal(wf_ex_graph, expected_wf_ex_graph) -class WorkflowConductorTest(WorkflowComposerTest, metaclass=abc.ABCMeta): +class WorkflowConductorTest(WorkflowComposerTest): def format_task_item( self, task_id,