diff --git a/.spelling b/.spelling index 8efb3ebb52..405acc5c29 100644 --- a/.spelling +++ b/.spelling @@ -3,6 +3,7 @@ # global dictionary is at the start, file overrides afterwards # one word per line, to define a file override use ' - filename' # where filename is relative to this configuration file +fraxtal Flashbots liveness pre-shared diff --git a/HISTORY.md b/HISTORY.md index c9ad35aff0..10ab46ab72 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,10 @@ # Release History - open AEA +## 1.58.0 (2024-10-03) + +AEA: +- Adds support for dictionary overrides #750, #761 + ## 1.57.0 (2024-09-24) AEA: diff --git a/SECURITY.md b/SECURITY.md index 6059da7f4c..c0aa0f6514 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -8,8 +8,8 @@ The following table shows which versions of `open-aea` are currently being suppo | Version | Supported | |------------| ------------------ | -| `1.57.x` | :white_check_mark: | -| `< 1.57.0` | :x: | +| `1.58.x` | :white_check_mark: | +| `< 1.58.0` | :x: | ## Reporting a Vulnerability diff --git a/aea/__version__.py b/aea/__version__.py index d68f585c79..08aa85260f 100644 --- a/aea/__version__.py +++ b/aea/__version__.py @@ -23,7 +23,7 @@ __title__ = "open-aea" __description__ = "Open Autonomous Economic Agent framework (without vendor lock-in)" __url__ = "https://github.com/valory-xyz/open-aea.git" -__version__ = "1.57.0" +__version__ = "1.58.0" __author__ = "Valory AG" __license__ = "Apache-2.0" __copyright__ = "2021 Valory AG, 2019 Fetch.AI Limited" diff --git a/aea/configurations/validation.py b/aea/configurations/validation.py index 568194e311..838c02b086 100644 --- a/aea/configurations/validation.py +++ b/aea/configurations/validation.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # -# Copyright 2022-2023 Valory AG +# Copyright 2022-2024 Valory AG # Copyright 2018-2021 Fetch.AI Limited # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,13 @@ # # ------------------------------------------------------------------------------ """Implementation of the configuration validation.""" + import inspect import json import os from collections import OrderedDict from copy import deepcopy +from functools import reduce from pathlib import Path from typing import Any, Dict, Iterator, List, Optional, Tuple @@ -36,7 +38,7 @@ from aea.configurations.constants import AGENT from aea.configurations.data_types import ComponentId, ComponentType, PublicId from aea.exceptions import AEAValidationError -from aea.helpers.base import dict_to_path_value +from aea.helpers.base import dict_to_path_value, update_nested_dict from aea.helpers.env_vars import is_env_variable from aea.helpers.io import open_file @@ -295,12 +297,26 @@ def validate_data_with_pattern( excludes_: List[Tuple[str]] = [] else: excludes_ = excludes - pattern_path_value = { + original_config = { tuple(path): value for path, value in dict_to_path_value(pattern) } - data_path_value = {tuple(path): value for path, value in dict_to_path_value(data)} + overrides = {tuple(path): value for path, value in dict_to_path_value(data)} errors = [] + # this is a workaround to fix the type of numeric keys as they can only be represented as strs in the json overrides + for path in original_config: + path_as_str = tuple(map(str, path)) + if path_as_str in overrides and path not in overrides: + value = overrides[path_as_str] + del overrides[path_as_str] + up_to_last_key = data + for key in path_as_str[:-1]: + up_to_last_key = up_to_last_key[key] + del up_to_last_key[path_as_str[-1]] + overrides[path] = value + vals = reduce(lambda d, key: {key: d}, reversed(path), value) + update_nested_dict(data, vals) + def check_excludes(path: Tuple[str, ...]) -> bool: for exclude in excludes_: if len(exclude) > len(path): # pragma: nocover @@ -315,17 +331,17 @@ def is_a_dict_override(path: Tuple[str, ...]) -> bool: flag = False while len(path) > 0: path = path[:-1] - if path in pattern_path_value: - pattern_value = pattern_path_value[path] + if path in original_config: + pattern_value = original_config[path] flag = isinstance(pattern_value, OrderedDict) break return flag - for path, new_value in data_path_value.items(): + for path, new_value in overrides.items(): if check_excludes(path): continue - if path not in pattern_path_value: + if path not in original_config: if not is_a_dict_override(path=(*path,)): errors.append( f"Attribute `{'.'.join(path)}` is not allowed to be updated!" @@ -333,7 +349,7 @@ def is_a_dict_override(path: Tuple[str, ...]) -> bool: continue - pattern_value = pattern_path_value[path] + pattern_value = original_config[path] if pattern_value is None: # not possible to determine data type for optional value not set diff --git a/aea/helpers/base.py b/aea/helpers/base.py index 0594494d7a..785989bfd8 100644 --- a/aea/helpers/base.py +++ b/aea/helpers/base.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # -# Copyright 2022-2023 Valory AG +# Copyright 2022-2024 Valory AG # Copyright 2018-2021 Fetch.AI Limited # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -711,10 +711,14 @@ def dict_to_path_value( """Convert dict to sequence of terminal path build of keys and value.""" path = path or [] for key, value in data.items(): + # terminal value if isinstance(value, Mapping) and value: - # terminal value + # yielding here allows for higher level dict overriding + yield path + [key], value + # recursing to the next level of the dict for p, v in dict_to_path_value(value, path + [key]): yield p, v + # non-terminal value else: yield path + [key], value @@ -1087,3 +1091,13 @@ def prepend_if_not_absolute(path: PathLike, prefix: PathLike) -> PathLike: :return: the same path if absolute, else the prepended path. """ return path if Path(path).is_absolute() else Path(prefix) / path + + +def update_nested_dict(dict_: dict, nested_update: dict) -> dict: + """Update a nested dictionary.""" + for key, value in nested_update.items(): + if isinstance(value, dict): + dict_[key] = update_nested_dict(dict_.get(key, {}), value) + else: + dict_[key] = value + return dict_ diff --git a/aea/helpers/env_vars.py b/aea/helpers/env_vars.py index 43f62f4b5b..d1b865a8ae 100644 --- a/aea/helpers/env_vars.py +++ b/aea/helpers/env_vars.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # -# Copyright 2022-2023 Valory AG +# Copyright 2022-2024 Valory AG # Copyright 2018-2019 Fetch.AI Limited # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -34,6 +34,11 @@ ENV_VARIABLE_RE = re.compile(r"^\$\{(([A-Z0-9_]+):?)?([a-z]+)?(:(.+))?}$") +MODELS = "models" +ARGS = "args" +ARGS_LEVEL_FROM_MODELS = 2 +ARG_LEVEL_FROM_MODELS = ARGS_LEVEL_FROM_MODELS + 1 +RESTRICTION_EXCEPTIONS = frozenset({"setup", "genesis_config"}) def is_env_variable(value: Any) -> bool: @@ -41,10 +46,35 @@ def is_env_variable(value: Any) -> bool: return isinstance(value, str) and bool(ENV_VARIABLE_RE.match(value)) -def export_path_to_env_var_string(export_path: List[str]) -> str: - """Conver export path to environment variable string.""" +def restrict_model_args(export_path: List[str]) -> Tuple[List[str], List[str]]: + """Do not allow more levels than one for a model's argument.""" + restricted = [] + result = [] + for i, current_path in enumerate(export_path): + result.append(current_path) + args_level = i + ARGS_LEVEL_FROM_MODELS + arg_level = i + ARG_LEVEL_FROM_MODELS + if ( + current_path == MODELS + and arg_level < len(export_path) + and export_path[args_level] == ARGS + and export_path[arg_level] not in RESTRICTION_EXCEPTIONS + ): + # do not allow more levels than one for a model's argument + arg_content_level = arg_level + 1 + result.extend(export_path[i + 1 : arg_content_level]) + # store the restricted part of the path + for j in range(arg_content_level, len(export_path)): + restricted.append(export_path[j]) + break + return restricted, result + + +def export_path_to_env_var_string(export_path: List[str]) -> Tuple[List[str], str]: + """Convert export path to environment variable string.""" + restricted, export_path = restrict_model_args(export_path) env_var_string = "_".join(map(str, export_path)) - return env_var_string.upper() + return restricted, env_var_string.upper() NotSet = object() @@ -149,7 +179,7 @@ def apply_env_variables( data, env_variables, default_value, - default_var_name=export_path_to_env_var_string(export_path=path), + default_var_name=export_path_to_env_var_string(export_path=path)[1], ) return data @@ -242,35 +272,76 @@ def is_strict_list(data: Union[List, Tuple]) -> bool: return is_strict +def list_to_nested_dict(lst: list, val: Any) -> dict: + """Convert a list to a nested dict.""" + nested_dict = val + for item in reversed(lst): + nested_dict = {item: nested_dict} + return nested_dict + + +def ensure_dict(dict_: Dict[str, Union[dict, str]]) -> dict: + """Return the given dictionary converting any values which are json strings as dicts.""" + return {k: json.loads(v) for k, v in dict_.items() if isinstance(v, str)} + + +def ensure_json_content(dict_: dict) -> dict: + """Return the given dictionary converting any nested dictionary values as json strings.""" + return {k: json.dumps(v) for k, v in dict_.items() if isinstance(v, dict)} + + +def merge_dicts(a: dict, b: dict) -> dict: + """Merge two dictionaries.""" + # shallow copy of `a` + merged = {**a} + for key, value in b.items(): + if key in merged and isinstance(merged[key], dict) and isinstance(value, dict): + # recursively merge nested dictionaries + merged[key] = merge_dicts(merged[key], value) + else: + # if not a nested dictionary, just take the value from `b` + merged[key] = value + return merged + + def generate_env_vars_recursively( data: Union[Dict, List], export_path: List[str], ) -> Dict: """Generate environment variables recursively.""" - env_var_dict = {} + env_var_dict: Dict[str, Any] = {} if isinstance(data, dict): for key, value in data.items(): - env_var_dict.update( - generate_env_vars_recursively( - data=value, - export_path=[*export_path, key], - ) + res = generate_env_vars_recursively( + data=value, + export_path=[*export_path, key], ) + if res: + env_var = list(res.keys())[0] + if env_var in env_var_dict: + dicts = (ensure_dict(dict_) for dict_ in (env_var_dict, res)) + res = ensure_json_content(merge_dicts(*dicts)) + env_var_dict.update(res) elif isinstance(data, list): if is_strict_list(data=data): - env_var_dict[ - export_path_to_env_var_string(export_path=export_path) - ] = json.dumps(data, separators=(",", ":")) + restricted, path = export_path_to_env_var_string(export_path=export_path) + if restricted: + env_var_dict[path] = json.dumps(list_to_nested_dict(restricted, data)) + else: + env_var_dict[path] = json.dumps(data, separators=(",", ":")) else: for key, value in enumerate(data): - env_var_dict.update( - generate_env_vars_recursively( - data=value, - export_path=[*export_path, key], - ) + res = generate_env_vars_recursively( + data=value, + export_path=[*export_path, key], ) + env_var_dict.update(res) else: - env_var_dict[export_path_to_env_var_string(export_path=export_path)] = data + restricted, path = export_path_to_env_var_string(export_path=export_path) + if restricted: + env_var_dict[path] = json.dumps(list_to_nested_dict(restricted, data)) + else: + env_var_dict[path] = data return env_var_dict diff --git a/deploy-image/Dockerfile b/deploy-image/Dockerfile index ac0eead0b2..85308e6d7f 100644 --- a/deploy-image/Dockerfile +++ b/deploy-image/Dockerfile @@ -16,7 +16,7 @@ RUN apk add --no-cache go # aea installation RUN pip install --upgrade pip -RUN pip install --upgrade --force-reinstall open-aea[all]==1.57.0 "open-aea-cli-ipfs<2.0.0,>=1.57.0" +RUN pip install --upgrade --force-reinstall open-aea[all]==1.58.0 "open-aea-cli-ipfs<2.0.0,>=1.58.0" # directories and aea cli config WORKDIR /home/agents diff --git a/deploy-image/README.md b/deploy-image/README.md index 4e97bc4379..124a18d0ba 100644 --- a/deploy-image/README.md +++ b/deploy-image/README.md @@ -11,7 +11,7 @@ The example uses the `fetchai/my_first_aea` project. You will likely want to mod Install subversion, then download the example directory to your local working directory ``` bash -svn checkout https://github.com/valory-xyz/open-aea/tags/v1.57.0/packages packages +svn checkout https://github.com/valory-xyz/open-aea/tags/v1.58.0/packages packages ``` ### Modify scripts diff --git a/develop-image/docker-env.sh b/develop-image/docker-env.sh index fe2873d9c8..6951406d11 100755 --- a/develop-image/docker-env.sh +++ b/develop-image/docker-env.sh @@ -1,7 +1,7 @@ #!/bin/bash # Swap the following lines if you want to work with 'latest' -DOCKER_IMAGE_TAG=valory/open-aea-develop:1.57.0 +DOCKER_IMAGE_TAG=valory/open-aea-develop:1.58.0 # DOCKER_IMAGE_TAG=valory/open-aea-develop:latest DOCKER_BUILD_CONTEXT_DIR=.. diff --git a/docs/api/helpers/base.md b/docs/api/helpers/base.md index 64f5247146..64fc16e130 100644 --- a/docs/api/helpers/base.md +++ b/docs/api/helpers/base.md @@ -838,3 +838,13 @@ Prepend a path with a prefix, but only if not absolute the same path if absolute, else the prepended path. + + +#### update`_`nested`_`dict + +```python +def update_nested_dict(dict_: dict, nested_update: dict) -> dict +``` + +Update a nested dictionary. + diff --git a/docs/api/helpers/env_vars.md b/docs/api/helpers/env_vars.md index d34e6adb8e..ff0705f7db 100644 --- a/docs/api/helpers/env_vars.md +++ b/docs/api/helpers/env_vars.md @@ -14,15 +14,26 @@ def is_env_variable(value: Any) -> bool Check is variable string with env variable pattern. + + +#### restrict`_`model`_`args + +```python +def restrict_model_args(export_path: List[str]) -> Tuple[List[str], List[str]] +``` + +Do not allow more levels than one for a model's argument. + #### export`_`path`_`to`_`env`_`var`_`string ```python -def export_path_to_env_var_string(export_path: List[str]) -> str +def export_path_to_env_var_string( + export_path: List[str]) -> Tuple[List[str], str] ``` -Conver export path to environment variable string. +Convert export path to environment variable string. @@ -115,6 +126,46 @@ parameters: Boolean specifying whether it's a strict list or not + + +#### list`_`to`_`nested`_`dict + +```python +def list_to_nested_dict(lst: list, val: Any) -> dict +``` + +Convert a list to a nested dict. + + + +#### ensure`_`dict + +```python +def ensure_dict(dict_: Dict[str, Union[dict, str]]) -> dict +``` + +Return the given dictionary converting any values which are json strings as dicts. + + + +#### ensure`_`json`_`content + +```python +def ensure_json_content(dict_: dict) -> dict +``` + +Return the given dictionary converting any nested dictionary values as json strings. + + + +#### merge`_`dicts + +```python +def merge_dicts(a: dict, b: dict) -> dict +``` + +Merge two dictionaries. + #### generate`_`env`_`vars`_`recursively diff --git a/docs/upgrading.md b/docs/upgrading.md index fd0d368ea2..99e82dd8d1 100644 --- a/docs/upgrading.md +++ b/docs/upgrading.md @@ -9,6 +9,10 @@ Below we describe the additional manual steps required to upgrade between differ ### Upgrade guide +## `v1.57.0` to `v1.58.0` + +- No backwards incompatible changes + ## `v1.56.0` to `v1.57.0` - No backwards incompatible changes diff --git a/examples/tac_deploy/Dockerfile b/examples/tac_deploy/Dockerfile index 294a703361..88a1216780 100644 --- a/examples/tac_deploy/Dockerfile +++ b/examples/tac_deploy/Dockerfile @@ -19,7 +19,7 @@ RUN apk add --no-cache go # aea installation RUN python -m pip install --upgrade pip -RUN pip install --upgrade --force-reinstall open-aea[all]==1.57.0 +RUN pip install --upgrade --force-reinstall open-aea[all]==1.58.0 # directories and aea cli config COPY /.aea /home/.aea diff --git a/plugins/aea-cli-benchmark/setup.py b/plugins/aea-cli-benchmark/setup.py index db4f1001c4..6143b38898 100755 --- a/plugins/aea-cli-benchmark/setup.py +++ b/plugins/aea-cli-benchmark/setup.py @@ -26,7 +26,7 @@ setup( name="open-aea-cli-benchmark", - version="1.57.0", + version="1.58.0", author="Valory AG", license="Apache-2.0", description="CLI extension for AEA framework benchmarking.", diff --git a/plugins/aea-cli-ipfs/setup.py b/plugins/aea-cli-ipfs/setup.py index 0de1038037..054f1ecc73 100755 --- a/plugins/aea-cli-ipfs/setup.py +++ b/plugins/aea-cli-ipfs/setup.py @@ -28,7 +28,7 @@ setup( name="open-aea-cli-ipfs", - version="1.57.0", + version="1.58.0", author="Valory AG", license="Apache-2.0", description="CLI extension for open AEA framework wrapping IPFS functionality.", diff --git a/plugins/aea-ledger-cosmos/setup.py b/plugins/aea-ledger-cosmos/setup.py index ad94811e63..15764e2628 100644 --- a/plugins/aea-ledger-cosmos/setup.py +++ b/plugins/aea-ledger-cosmos/setup.py @@ -26,7 +26,7 @@ setup( name="open-aea-ledger-cosmos", - version="1.57.0", + version="1.58.0", author="Valory AG", license="Apache-2.0", description="Python package wrapping the public and private key cryptography and ledger api of Cosmos.", diff --git a/plugins/aea-ledger-ethereum-flashbots/setup.py b/plugins/aea-ledger-ethereum-flashbots/setup.py index 7d54044b20..ac5236e50a 100644 --- a/plugins/aea-ledger-ethereum-flashbots/setup.py +++ b/plugins/aea-ledger-ethereum-flashbots/setup.py @@ -25,7 +25,7 @@ setup( name="open-aea-ledger-ethereum-flashbots", - version="1.57.0", + version="1.58.0", author="Valory AG", license="Apache-2.0", description="Python package extending the default open-aea ethereum ledger plugin to add support for flashbots.", @@ -41,7 +41,7 @@ }, python_requires=">=3.9,<4.0", install_requires=[ - "open-aea-ledger-ethereum~=1.57.0", + "open-aea-ledger-ethereum~=1.58.0", "open-aea-flashbots==1.4.0", ], tests_require=["pytest"], diff --git a/plugins/aea-ledger-ethereum-hwi/setup.py b/plugins/aea-ledger-ethereum-hwi/setup.py index 563ca8209e..3726a94213 100644 --- a/plugins/aea-ledger-ethereum-hwi/setup.py +++ b/plugins/aea-ledger-ethereum-hwi/setup.py @@ -25,7 +25,7 @@ setup( name="open-aea-ledger-ethereum-hwi", - version="1.57.0", + version="1.58.0", author="Valory AG", license="Apache-2.0", description="Python package wrapping the public and private key cryptography and support for hardware wallet interactions.", @@ -42,7 +42,7 @@ "web3>=6.0.0,<7", "ipfshttpclient==0.8.0a2", "eth-account>=0.8.0,<0.9.0", - "open-aea-ledger-ethereum~=1.57.0", + "open-aea-ledger-ethereum~=1.58.0", "ledgerwallet==0.1.3", "protobuf<4.25.0,>=4.21.6", "construct<=2.10.61", diff --git a/plugins/aea-ledger-ethereum/setup.py b/plugins/aea-ledger-ethereum/setup.py index 8ebeeeeb9f..a5aa034832 100644 --- a/plugins/aea-ledger-ethereum/setup.py +++ b/plugins/aea-ledger-ethereum/setup.py @@ -26,7 +26,7 @@ setup( name="open-aea-ledger-ethereum", - version="1.57.0", + version="1.58.0", author="Valory AG", license="Apache-2.0", description="Python package wrapping the public and private key cryptography and ledger api of Ethereum.", diff --git a/plugins/aea-ledger-fetchai/setup.py b/plugins/aea-ledger-fetchai/setup.py index 5197212049..684a2b9386 100644 --- a/plugins/aea-ledger-fetchai/setup.py +++ b/plugins/aea-ledger-fetchai/setup.py @@ -31,7 +31,7 @@ setup( name="open-aea-ledger-fetchai", - version="1.57.0", + version="1.58.0", author="Valory AG", license="Apache-2.0", description="Python package wrapping the public and private key cryptography and ledger API of Fetch.AI.", @@ -44,7 +44,7 @@ "test_tools/data/*", ] }, - install_requires=["open-aea-ledger-cosmos~=1.57.0"], + install_requires=["open-aea-ledger-cosmos~=1.58.0"], tests_require=["pytest"], entry_points={ "aea.cryptos": ["fetchai = aea_ledger_fetchai:FetchAICrypto"], diff --git a/plugins/aea-ledger-solana/setup.py b/plugins/aea-ledger-solana/setup.py index 60ac173189..ac05380354 100644 --- a/plugins/aea-ledger-solana/setup.py +++ b/plugins/aea-ledger-solana/setup.py @@ -25,7 +25,7 @@ setup( name="open-aea-ledger-solana", - version="1.57.0", + version="1.58.0", author="dassy23", license="Apache-2.0", description="Python package wrapping the public and private key cryptography and ledger api of solana.", diff --git a/scripts/install.ps1 b/scripts/install.ps1 index 6627b4ffd2..b09c3a98b1 100644 --- a/scripts/install.ps1 +++ b/scripts/install.ps1 @@ -34,7 +34,7 @@ function instal_choco_golang_gcc { } function install_aea { echo "Install aea" - $output=pip install open-aea[all]==1.57.0 --force --no-cache-dir 2>&1 |out-string; + $output=pip install open-aea[all]==1.58.0 --force --no-cache-dir 2>&1 |out-string; if ($LastExitCode -ne 0) { echo $output echo "AEA install failed!" diff --git a/scripts/install.sh b/scripts/install.sh index 74d54160f8..98aa47c211 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -42,7 +42,7 @@ function is_python_version_ok() { function install_aea (){ echo "Install AEA" - output=$(pip3 install --user open-aea[all]==1.57.0 --force --no-cache-dir) + output=$(pip3 install --user open-aea[all]==1.58.0 --force --no-cache-dir) if [[ $? -ne 0 ]]; then echo "$output" diff --git a/skaffold.yaml b/skaffold.yaml index 37d4fb517f..b67960e240 100644 --- a/skaffold.yaml +++ b/skaffold.yaml @@ -5,7 +5,7 @@ metadata: build: tagPolicy: envTemplate: - template: "1.57.0" + template: "1.58.0" artifacts: - image: valory/open-aea-develop docker: @@ -24,7 +24,7 @@ profiles: build: tagPolicy: envTemplate: - template: "1.57.0" + template: "1.58.0" artifacts: - image: valory/open-aea-docs docker: diff --git a/tests/test_cli/test_config.py b/tests/test_cli/test_config.py index e896557c4d..c1aa7971bb 100644 --- a/tests/test_cli/test_config.py +++ b/tests/test_cli/test_config.py @@ -462,7 +462,7 @@ def test_set_nested_attribute_not_allowed(self): assert result.exit_code == 1 assert ( result.exception.message - == "Attribute `behaviours.dummy.config.behaviour_arg_1` is not allowed to be updated!" + == "Attribute `behaviours.dummy.config` is not allowed to be updated!" ) def test_no_recognized_root(self): @@ -542,10 +542,11 @@ def test_attribute_not_found(self): catch_exceptions=False, ) - def test_set_fails_when_setting_non_primitive_type(self): + def test_incorrect_data_type(self): """Test that setting the 'dummy' skill behaviours fails because not a primitive type.""" with pytest.raises( - ClickException, match="Attribute `behaviours` is not allowed to be updated!" + ClickException, + match="For attribute `behaviours` `dict` data type is expected, but `str` was provided!", ): self.runner.invoke( cli, @@ -558,7 +559,7 @@ def test_get_fails_when_setting_nested_object(self): """Test that setting a nested object in 'dummy' skill fails because path is not valid.""" with pytest.raises( ClickException, - match=r"Attribute `non_existing_attribute.dummy` is not allowed to be updated!", + match=r"Attribute `non_existing_attribute` is not allowed to be updated!", ): self.runner.invoke( cli, diff --git a/tests/test_configurations/test_base.py b/tests/test_configurations/test_base.py index c2e3336956..27bab57e8c 100644 --- a/tests/test_configurations/test_base.py +++ b/tests/test_configurations/test_base.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # -# Copyright 2022-2023 Valory AG +# Copyright 2022-2024 Valory AG # Copyright 2018-2021 Fetch.AI Limited # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -298,7 +298,7 @@ def test_update_method_raises_error_if_skill_component_not_allowed(self): with pytest.raises( ValueError, - match="Attribute `behaviours.new_behaviour.args` is not allowed to be updated!", + match="Attribute `behaviours.new_behaviour` is not allowed to be updated!", ): skill_config.update(new_configurations) diff --git a/tests/test_configurations/test_validation.py b/tests/test_configurations/test_validation.py index 1e19a71fab..682be8eba4 100644 --- a/tests/test_configurations/test_validation.py +++ b/tests/test_configurations/test_validation.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # -# Copyright 2022 Valory AG +# Copyright 2022-2024 Valory AG # Copyright 2018-2021 Fetch.AI Limited # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -46,14 +46,15 @@ def test_compare_data_pattern(): assert not validate_data_with_pattern( {"a": "${var}"}, {"a": "string"}, skip_env_vars=True ) + assert not validate_data_with_pattern({"a": {}}, {"a": {"b": 12}}) errors = validate_data_with_pattern({"a": 12}, {"b": 12}) assert errors assert errors[0] == "Attribute `a` is not allowed to be updated!" - errors = validate_data_with_pattern({"a": {}}, {"a": {"b": 12}}) + errors = validate_data_with_pattern({"a": {"b": 12}}, {"a": {}}) assert errors - assert errors[0] == "Attribute `a` is not allowed to be updated!" + assert errors[0] == "Attribute `a.b` is not allowed to be updated!" def test_filter_data(): diff --git a/tests/test_helpers/test_env_vars.py b/tests/test_helpers/test_env_vars.py index e0fde93864..70a57dd884 100644 --- a/tests/test_helpers/test_env_vars.py +++ b/tests/test_helpers/test_env_vars.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # -# Copyright 2022-2023 Valory AG +# Copyright 2022-2024 Valory AG # Copyright 2018-2019 Fetch.AI Limited # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -118,7 +118,7 @@ def test_convert_value_str_to_type(): def test_env_var_string_generator(export_path: List[str], var_string: str) -> None: """Test `export_path_to_env_var_string` method""" - assert export_path_to_env_var_string(export_path=export_path) == var_string + assert export_path_to_env_var_string(export_path=export_path)[1] == var_string @pytest.mark.parametrize( diff --git a/user-image/Dockerfile b/user-image/Dockerfile index b15397fbcd..b03227dd60 100644 --- a/user-image/Dockerfile +++ b/user-image/Dockerfile @@ -7,7 +7,7 @@ ENV LANG C.UTF-8 RUN apt update && apt install -y python3.11-dev python3-pip -y && apt autoremove && apt autoclean RUN pip3 install --upgrade pip -RUN pip3 install "open-aea[all]==1.57.0" open-aea-cli-ipfs==1.57.0 +RUN pip3 install "open-aea[all]==1.58.0" open-aea-cli-ipfs==1.58.0 COPY user-image/openssl.cnf /etc/ssl diff --git a/user-image/docker-env.sh b/user-image/docker-env.sh index 98cb1fa9e4..b692f61277 100644 --- a/user-image/docker-env.sh +++ b/user-image/docker-env.sh @@ -1,7 +1,7 @@ #!/bin/bash # Swap the following lines if you want to work with 'latest' -DOCKER_IMAGE_TAG=valory/open-aea-user:1.57.0 +DOCKER_IMAGE_TAG=valory/open-aea-user:1.58.0 # DOCKER_IMAGE_TAG=valory/open-aea-user:latest DOCKER_BUILD_CONTEXT_DIR=..