diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index a05ca4dac6..3baaf31031 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -134,13 +134,13 @@ jobs: - name: License Check run: tox -e liccheck - name: AEA Package Hashes Check - run: tox -e hash_check -- --timeout 60.0 + run: tox -e hash-check - name: Check package versions in documentation - run: tox -e package_version_checks + run: tox -e package-version-checks - name: Check package dependencies - run: tox -e package_dependencies_checks + run: tox -e package-dependencies-checks - name: Check generate protocols - run: tox -e check_generate_all_protocols + run: tox -e check-generate-all-protocols - name: Generate Documentation run: tox -e docs @@ -189,11 +189,11 @@ jobs: - name: Install markdown-spellcheck run: sudo npm install -g markdown-spellcheck - name: Check Docs links and IPFS hashes - run: tox -e check_doc_links_hashes + run: tox -e check-doc-links-hashes - name: Check API Docs updated - run: tox -e check_api_docs + run: tox -e check-api-docs - name: Check spelling - run: tox -e spell_check + run: tox -e spell-check scan: name: gitleaks @@ -235,7 +235,7 @@ jobs: pip install -e .[all] - name: Check aea dependenices and imports run: | - tox -e dependencies_check + tox -e dependencies-check plugins_install_check: continue-on-error: False diff --git a/.spelling b/.spelling index 35fd9df774..72f02e5327 100644 --- a/.spelling +++ b/.spelling @@ -285,6 +285,11 @@ v0 ipfsdaemon py3.6 async +gnosis +abci +metaclass +api +gitleaks - docs/language-agnostic-definition.md fetchai protocol_id diff --git a/HISTORY.md b/HISTORY.md index 678fc14318..035daa2a83 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -10,7 +10,7 @@ AEA: - Adds check to make sure all the packages in an AEA project are listed in the `aea-config.yaml` - Fixes a bug related to async function call on `TCPSocketProtocol` - Updates transaction building to handle gas estimation properly -- Update `ContractConfig` class to include contract dependencies in the depedency list +- Update `ContractConfig` class to include contract dependencies in the dependency list Docs: - Adds missing command on the `http-echo-demo.md` doc. diff --git a/Makefile b/Makefile index aa675d1246..a3d08481e6 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ .PHONY: clean -clean: clean-build clean-pyc clean-test clean-docs +clean: clean-test clean-build clean-pyc clean-docs .PHONY: clean-build clean-build: @@ -9,6 +9,7 @@ clean-build: rm -fr pip-wheel-metadata find . -name '*.egg-info' -exec rm -fr {} + find . -name '*.egg' -exec rm -fr {} + + find . -type d -name __pycache__ -exec rm -rv {} + rm -fr Pipfile.lock rm -rf plugins/*/build rm -rf plugins/*/dist @@ -35,42 +36,20 @@ clean-test: rm -fr .hypothesis rm -fr .pytest_cache rm -fr .mypy_cache/ - rm -fr input_file - rm -fr output_file + rm -fr .hypothesis/ find . -name 'log.txt' -exec rm -fr {} + find . -name 'log.*.txt' -exec rm -fr {} + -.PHONY: lint -lint: - black aea benchmark examples packages plugins scripts tests - isort aea benchmark examples packages plugins scripts tests - flake8 aea benchmark examples packages plugins scripts tests - vulture aea scripts/whitelist.py --exclude "*_pb2.py" - darglint aea benchmark examples libs packages plugins scripts - -.PHONY: pylint -pylint: - pylint -j4 aea benchmark packages scripts plugins/aea-ledger-fetchai/aea_ledger_fetchai plugins/aea-ledger-ethereum/aea_ledger_ethereum plugins/aea-ledger-cosmos/aea_ledger_cosmos plugins/aea-cli-ipfs/aea_cli_ipfs examples/* - -.PHONY: static -static: - mypy aea benchmark examples --disallow-untyped-defs - mypy packages tests plugins/aea-ledger-fetchai/aea_ledger_fetchai plugins/aea-ledger-ethereum/aea_ledger_ethereum plugins/aea-ledger-cosmos/aea_ledger_cosmos plugins/aea-cli-ipfs/aea_cli_ipfs - -.PHONY: package_checks +.PHONY: package-checks package_checks: - python -m aea.cli hash all --check - python -m aea.cli hash all --packages-dir=./tests/data/packages --check - python scripts/check_package_versions_in_docs.py - python -m aea.cli check-packages + tox -e hash-check + tox -e package-version-checks + tox -e package-dependencies-checks .PHONY: docs docs: mkdocs build --clean -.PHONY: common_checks -common_checks: security misc_checks lint static docs - .PHONY: test test: pytest -rfE plugins/aea-ledger-fetchai/tests --cov=aea_ledger_fetchai --cov-report=term --cov-report=term-missing --cov-config=.coveragerc @@ -128,12 +107,7 @@ release: v := $(shell pip -V | grep virtualenvs) .PHONY: all-checks -all-checks: - make clean \ - && make formatters \ - && make code-checks \ - && make common-checks \ - && make security \ +all-checks: clean formatters code-checks common-checks-1 common-checks-2 security .PHONY: new_env new_env: clean @@ -191,26 +165,19 @@ security: # update copyright headers .PHONY: generators generators: + tox -e fix-copyright python -m aea.cli generate-all-protocols python -m aea.cli generate-all-protocols tests/data/packages python -m aea.cli hash all python -m aea.cli hash all --packages-dir=./tests/data/packages - python scripts/generate_api_docs.py - python scripts/check_copyright_notice.py - python scripts/check_doc_ipfs_hashes.py --fix + tox -e generate-api-documentation + tox -e fix-doc-hashes -.PHONY: common-checks +.PHONY: common-checks-1 common-checks: - tox -p -e check-copyright -e hash_check -e package_dependencies_checks - -.PHONY: doc-checks -doc-checks: - tox -e check_doc_links_hashes -e check_api_docs - -.PHONY: copyright -copyright: - python scripts/check_copyright_notice.py + tox -p -e check-copyright -e hash_check -e package-dependencies-checks -.PHONY: check-copyright -check-copyright: - tox -e check-copyright +.PHONY: common-checks-2 +common-checks-2: + tox -e check-api-docs + tox -e check-doc-links-hashes diff --git a/aea/cli/add.py b/aea/cli/add.py index 285409eb72..d83a60d5af 100644 --- a/aea/cli/add.py +++ b/aea/cli/add.py @@ -208,7 +208,7 @@ def fetch_item_remote( if get_default_remote_registry() == REMOTE_IPFS: try: - return fetch_ipfs(item_type, item_public_id, dest_path) + return cast(Path, fetch_ipfs(item_type, item_public_id, dest_path)) except HashNotProvided: click.echo(f"Hash was not provided for: {item_public_id}") click.echo("Will try with http repository.") diff --git a/aea/cli/push.py b/aea/cli/push.py index d7163469d7..b922e808af 100644 --- a/aea/cli/push.py +++ b/aea/cli/push.py @@ -208,7 +208,7 @@ def push_item_ipfs(component_path: Path, public_id: PublicId) -> None: ) ipfs_tool = IPFSTool(get_ipfs_node_multiaddr()) - _, package_hash, _ = ipfs_tool.add(component_path) + _, package_hash, _ = ipfs_tool.add(str(component_path)) package_hash = to_v1(package_hash) click.echo("Pushed component with:") diff --git a/docs/api/plugins/aea_ledger_ethereum/ethereum.md b/docs/api/plugins/aea_ledger_ethereum/ethereum.md index 3fbbe06d8e..0778ac57c4 100644 --- a/docs/api/plugins/aea_ledger_ethereum/ethereum.md +++ b/docs/api/plugins/aea_ledger_ethereum/ethereum.md @@ -39,12 +39,11 @@ Returns multiplier value. #### estimate`_`priority`_`fee ```python -def estimate_priority_fee(web3_object: Web3, base_fee_gwei: int, - block_number: int, - priority_fee_estimation_trigger: int, - default_priority_fee: int, fee_history_blocks: int, - fee_history_percentile: int, - priority_fee_increase_boundary: int) -> int +def estimate_priority_fee( + web3_object: Web3, base_fee_gwei: int, block_number: int, + priority_fee_estimation_trigger: int, default_priority_fee: int, + fee_history_blocks: int, fee_history_percentile: int, + priority_fee_increase_boundary: int) -> Optional[int] ``` Estimate priority fee from base fee. @@ -72,7 +71,8 @@ Get the gas price strategy. def get_gas_price_strategy_eip1559_polygon( gas_endpoint: str, fallback_estimate: Dict[str, Optional[int]], - speed: Optional[str] = SPEED_FAST) -> Callable[[], Dict[str, Wei]] + speed: Optional[str] = SPEED_FAST +) -> Callable[[Any, Any], Dict[str, Wei]] ``` Get the gas price strategy. @@ -793,18 +793,10 @@ the contract instance #### get`_`deploy`_`transaction ```python -def get_deploy_transaction( - contract_interface: Dict[str, str], - deployer_address: Address, - value: int = 0, - gas: Optional[int] = None, - max_fee_per_gas: Optional[int] = None, - max_priority_fee_per_gas: Optional[str] = None, - gas_price: Optional[str] = None, - gas_price_strategy: Optional[str] = None, - gas_price_strategy_extra_config: Optional[Dict] = None, - raise_on_try: bool = False, - **kwargs: Any) -> Optional[JSONLike] +def get_deploy_transaction(contract_interface: Dict[str, str], + deployer_address: Address, + raise_on_try: bool = False, + **kwargs: Any) -> Optional[JSONLike] ``` Get the transaction to deploy the smart contract. @@ -813,13 +805,6 @@ Get the transaction to deploy the smart contract. - `contract_interface`: the contract interface. - `deployer_address`: The address that will deploy the contract. -- `value`: value to send to contract (in Wei) -- `gas`: the gas to be used (in Wei) -- `max_fee_per_gas`: maximum amount you’re willing to pay, inclusive of `baseFeePerGas` and `maxPriorityFeePerGas`. The difference between `maxFeePerGas` and `baseFeePerGas + maxPriorityFeePerGas` is refunded (in Wei). -- `max_priority_fee_per_gas`: the part of the fee that goes to the miner (in Wei). -- `gas_price`: the gas price (in Wei) -- `gas_price_strategy`: the gas price strategy to be used. -- `gas_price_strategy_extra_config`: extra config for gas price strategy. - `raise_on_try`: whether the method will raise or log on error - `kwargs`: keyword arguments @@ -875,8 +860,8 @@ the call result ```python def build_transaction(contract_instance: Any, method_name: str, - method_args: Dict, - tx_args: Dict, + method_args: Optional[Dict[Any, Any]], + tx_args: Optional[Dict[Any, Any]], raise_on_try: bool = False) -> Optional[JSONLike] ``` diff --git a/docs/gym-skill.md b/docs/gym-skill.md index 8ba38d9036..80004b1c01 100644 --- a/docs/gym-skill.md +++ b/docs/gym-skill.md @@ -1,4 +1,4 @@ -The AEA gym skill demonstrates how a custom Reinforcement Learning agent, that uses OpenAI's gym library, may be embedded into an AEA skill and connection. +The AEA gym skill demonstrates how a custom Reinforcement Learning agent, that uses OpenAI's gym library, may be embedded into an AEA skill and connection. ### Discussion diff --git a/docs/limits.md b/docs/limits.md index 7321449281..677cd10c0b 100644 --- a/docs/limits.md +++ b/docs/limits.md @@ -154,7 +154,7 @@ This could be taken further, and a reduced spec version for Nuitka and it would be desirable to explore how useful and practical this would be in the context of AEA. +Python is not a compiled language. However, various projects attempt this, e.g. Nuitka and it would be desirable to explore how useful and practical this would be in the context of AEA. #### DID integration diff --git a/examples/gym_ex/proxy/env.py b/examples/gym_ex/proxy/env.py index f0a5c0f8ca..25c6cf2453 100755 --- a/examples/gym_ex/proxy/env.py +++ b/examples/gym_ex/proxy/env.py @@ -139,7 +139,7 @@ def step(self, action: Action) -> Feedback: return observation, reward, done, info - def render(self, mode="human") -> None: + def render(self, mode: str = "human") -> None: """ Render the environment. @@ -177,7 +177,7 @@ def close(self) -> None: self._disconnect() - def _connect(self): + def _connect(self) -> None: """Connect to this proxy environment. It starts a proxy agent that can interact with the framework.""" if cast(Thread, self._agent_thread).is_alive(): raise ValueError("Agent already running.") @@ -186,7 +186,7 @@ def _connect(self): while not self._agent.runtime.is_running: # check agent completely running time.sleep(0.01) - def _disconnect(self): + def _disconnect(self) -> None: """Disconnect from this proxy environment. It stops the proxy agent and kills its thread.""" self._agent.stop() cast(Thread, self._agent_thread).join() diff --git a/plugins/aea-cli-ipfs/aea_cli_ipfs/ipfs_utils.py b/plugins/aea-cli-ipfs/aea_cli_ipfs/ipfs_utils.py index ab515fd1c8..a3647d0ff0 100644 --- a/plugins/aea-cli-ipfs/aea_cli_ipfs/ipfs_utils.py +++ b/plugins/aea-cli-ipfs/aea_cli_ipfs/ipfs_utils.py @@ -23,7 +23,7 @@ import signal import subprocess # nosec from pathlib import Path -from typing import Dict, List, Optional, Set, Tuple, cast +from typing import Dict, IO, List, Optional, Set, Tuple, cast import ipfshttpclient # type: ignore import requests @@ -163,7 +163,11 @@ def start(self) -> None: env=os.environ.copy(), ) empty_outputs = 0 - for stdout_line in iter(self.process.stdout.readline, ""): + + if self.process.stdout is None: + raise RuntimeError("Could not start IPFS daemon.") + + for stdout_line in iter(cast(IO[bytes], self.process.stdout).readline, ""): if b"Daemon is ready" in stdout_line: break if stdout_line == b"": @@ -175,7 +179,10 @@ def stop(self) -> None: # pragma: nocover """Terminate the ipfs daemon if it was started internally.""" if self.process is None: return - self.process.stdout.close() + + if self.process.stdout is not None: + self.process.stdout.close() + self.process.send_signal(signal.SIGTERM) self.process.wait(timeout=30) poll = self.process.poll() @@ -207,7 +214,7 @@ def __init__(self, addr: Optional[str] = None): if addr is None: addr = os.environ.get("OPEN_AEA_IPFS_ADDR", DEFAULT_IPFS_URL) - _, host, *_ = resolve_addr(addr) # verify addr + _, host, *_ = resolve_addr(cast(str, addr)) # verify addr self._addr = addr self.is_remote = is_remote_addr(host) diff --git a/plugins/aea-cli-ipfs/aea_cli_ipfs/registry.py b/plugins/aea-cli-ipfs/aea_cli_ipfs/registry.py index 1c51e70bbf..66e3b7214a 100644 --- a/plugins/aea-cli-ipfs/aea_cli_ipfs/registry.py +++ b/plugins/aea-cli-ipfs/aea_cli_ipfs/registry.py @@ -164,7 +164,7 @@ def fetch_ipfs( ipfs_tool = IPFSTool(addr=DEFAULT_IPFS_URL_LOCAL) try: - package_hash = public_id.hash + package_hash: Optional[str] = public_id.hash except ValueError: package_hash = ( None if remote else get_ipfs_hash_from_public_id(item_type, public_id) diff --git a/plugins/aea-ledger-cosmos/aea_ledger_cosmos/cosmos.py b/plugins/aea-ledger-cosmos/aea_ledger_cosmos/cosmos.py index 5519d3d7da..b059846ec9 100644 --- a/plugins/aea-ledger-cosmos/aea_ledger_cosmos/cosmos.py +++ b/plugins/aea-ledger-cosmos/aea_ledger_cosmos/cosmos.py @@ -263,7 +263,7 @@ def get_event_attributes(tx_receipt: JSONLike) -> Dict: """ return { i["key"]: i["value"] - for i in chain(*[i["attributes"] for i in tx_receipt["logs"][0]["events"]]) + for i in chain(*[i["attributes"] for i in tx_receipt["logs"][0]["events"]]) # type: ignore } @classmethod @@ -1307,7 +1307,7 @@ def _get_transaction( ) # Get account and signer info for each sender - signer_infos: List[SignerInfo] = [] + signer_infos: List[SignerInfo] = [] # type: ignore sign_data: JSONLike = {} for from_address, pub_key, sequence, account_number in zip( from_addresses, pub_keys, sequences, account_numbers diff --git a/plugins/aea-ledger-ethereum/aea_ledger_ethereum/ethereum.py b/plugins/aea-ledger-ethereum/aea_ledger_ethereum/ethereum.py index 1e5396f506..f877e54fc6 100644 --- a/plugins/aea-ledger-ethereum/aea_ledger_ethereum/ethereum.py +++ b/plugins/aea-ledger-ethereum/aea_ledger_ethereum/ethereum.py @@ -91,7 +91,6 @@ FALLBACK_ESTIMATE = { "maxFeePerGas": to_wei(20, "gwei"), "maxPriorityFeePerGas": to_wei(DEFAULT_PRIORITY_FEE, "gwei"), - "baseFee": None, } PRIORITY_FEE_INCREASE_BOUNDARY = 200 # percentage @@ -158,7 +157,7 @@ def estimate_priority_fee( fee_history_blocks: int, fee_history_percentile: int, priority_fee_increase_boundary: int, -) -> int: +) -> Optional[int]: """Estimate priority fee from base fee.""" if base_fee_gwei < priority_fee_estimation_trigger: @@ -226,7 +225,7 @@ def eip1559_price_strategy( estimated_priority_fee = estimate_priority_fee( web3, - base_fee_gwei, + cast(int, base_fee_gwei), block_number, priority_fee_estimation_trigger=priority_fee_estimation_trigger, default_priority_fee=default_priority_fee, @@ -244,7 +243,7 @@ def eip1559_price_strategy( max_priority_fee_per_gas = max( estimated_priority_fee, to_wei(default_priority_fee, "gwei") ) - multiplier = get_base_fee_multiplier(base_fee_gwei) + multiplier = get_base_fee_multiplier(cast(int, base_fee_gwei)) potential_max_fee = base_fee * multiplier max_fee_per_gas = ( @@ -271,7 +270,7 @@ def get_gas_price_strategy_eip1559_polygon( gas_endpoint: str, fallback_estimate: Dict[str, Optional[int]], speed: Optional[str] = SPEED_FAST, -) -> Callable[[], Dict[str, Wei]]: +) -> Callable[[Any, Any], Dict[str, Wei]]: """Get the gas price strategy.""" def eip1559_price_strategy( @@ -999,11 +998,11 @@ def _get_gas_price_strategy( return None _default_logger.debug(f"Using strategy: {gas_price_strategy}") - gas_price_strategy_getter = self._gas_price_strategy_callables.get( - gas_price_strategy, None - ) + gas_price_strategy_getter = self._gas_price_strategy_callables[ + gas_price_strategy + ] - parameters = DEFAULT_GAS_PRICE_STRATEGIES.get(gas_price_strategy) + parameters = cast(dict, DEFAULT_GAS_PRICE_STRATEGIES.get(gas_price_strategy)) parameters.update(self._gas_price_strategies.get(gas_price_strategy, {})) parameters.update(extra_config or {}) return gas_price_strategy, gas_price_strategy_getter(**parameters) @@ -1291,13 +1290,6 @@ def get_deploy_transaction( # pylint: disable=arguments-differ self, contract_interface: Dict[str, str], deployer_address: Address, - value: int = 0, - gas: Optional[int] = None, - max_fee_per_gas: Optional[int] = None, - max_priority_fee_per_gas: Optional[str] = None, - gas_price: Optional[str] = None, - gas_price_strategy: Optional[str] = None, - gas_price_strategy_extra_config: Optional[Dict] = None, raise_on_try: bool = False, **kwargs: Any, ) -> Optional[JSONLike]: @@ -1306,17 +1298,38 @@ def get_deploy_transaction( # pylint: disable=arguments-differ :param contract_interface: the contract interface. :param deployer_address: The address that will deploy the contract. - :param value: value to send to contract (in Wei) - :param gas: the gas to be used (in Wei) - :param max_fee_per_gas: maximum amount you’re willing to pay, inclusive of `baseFeePerGas` and `maxPriorityFeePerGas`. The difference between `maxFeePerGas` and `baseFeePerGas + maxPriorityFeePerGas` is refunded (in Wei). - :param max_priority_fee_per_gas: the part of the fee that goes to the miner (in Wei). - :param gas_price: the gas price (in Wei) - :param gas_price_strategy: the gas price strategy to be used. - :param gas_price_strategy_extra_config: extra config for gas price strategy. :param raise_on_try: whether the method will raise or log on error :param kwargs: keyword arguments :return: the transaction dictionary. """ + + # value to send to contract (in Wei) + value: int = kwargs.pop("value", 0) + + # the gas to be used (in Wei) + gas: Optional[int] = kwargs.pop("gas", None) + + # maximum amount you’re willing to pay, inclusive of `baseFeePerGas` and + # `maxPriorityFeePerGas`. The difference between `maxFeePerGas` and + # `baseFeePerGas + maxPriorityFeePerGas` is refunded (in Wei). + max_fee_per_gas: Optional[int] = kwargs.pop("max_fee_per_gas", None) + + # the part of the fee that goes to the miner (in Wei). + max_priority_fee_per_gas: Optional[str] = kwargs.pop( + "max_priority_fee_per_gas", None + ) + + # the gas price (in Wei) + gas_price: Optional[str] = kwargs.pop("gas_price", None) + + # the gas price strategy to be used. + gas_price_strategy: Optional[str] = kwargs.pop("gas_price_strategy", None) + + # extra config for gas price strategy. + gas_price_strategy_extra_config: Optional[Dict] = kwargs.pop( + "gas_price_strategy_extra_config", None + ) + transaction: Optional[JSONLike] = None _deployer_address = self.api.toChecksumAddress(deployer_address) nonce = self._try_get_transaction_count( @@ -1408,8 +1421,8 @@ def build_transaction( # pylint: disable=too-many-arguments self, contract_instance: Any, method_name: str, - method_args: Dict, - tx_args: Dict, + method_args: Optional[Dict[Any, Any]], + tx_args: Optional[Dict[Any, Any]], raise_on_try: bool = False, ) -> Optional[JSONLike]: """Prepare a transaction @@ -1421,8 +1434,17 @@ def build_transaction( # pylint: disable=too-many-arguments :param raise_on_try: whether the method will raise or log on error :return: the transaction """ + + if method_args is None: + raise ValueError("Argument 'method_args' cannot be 'None'.") + method = getattr(contract_instance.functions, method_name) - tx = method(**method_args) + tx = method(**cast(Dict, method_args)) + + if tx_args is None: + raise ValueError("Argument 'tx_args' cannot be 'None'.") + + tx_args = cast(Dict, tx_args) nonce = self.api.eth.get_transaction_count(tx_args["sender_address"]) tx_params = { diff --git a/plugins/aea-ledger-ethereum/tests/test_ethereum.py b/plugins/aea-ledger-ethereum/tests/test_ethereum.py index cd60326567..e2f5301185 100644 --- a/plugins/aea-ledger-ethereum/tests/test_ethereum.py +++ b/plugins/aea-ledger-ethereum/tests/test_ethereum.py @@ -23,6 +23,7 @@ import logging import math import random +import re import tempfile import time from pathlib import Path @@ -487,7 +488,6 @@ def test_gas_price_strategy_eip1559() -> None: gas_stregy = callable_(web3, "tx_params") assert all([key in gas_stregy for key in ["maxFeePerGas", "maxPriorityFeePerGas"]]) - assert all([value > 1e8 for value in gas_stregy.values()]) @@ -518,8 +518,6 @@ def test_gas_price_strategy_eip1559_estimate_none() -> None: assert all([key in gas_stregy for key in ["maxFeePerGas", "maxPriorityFeePerGas"]]) - assert gas_stregy["baseFee"] is None - def test_gas_price_strategy_eip1559_fallback() -> None: """Test eip1559 based gas price strategy.""" @@ -550,8 +548,6 @@ def test_gas_price_strategy_eip1559_fallback() -> None: assert all([key in gas_stregy for key in ["maxFeePerGas", "maxPriorityFeePerGas"]]) - assert gas_stregy["baseFee"] is None - def test_gas_price_strategy_eth_gasstation(): """Test the gas price strategy when using eth gasstation.""" @@ -674,6 +670,25 @@ def pass_tx_params(tx_params): eth_api = EthereumApi(**ethereum_testnet_config) + with pytest.raises( + ValueError, match=re.escape("Argument 'method_args' cannot be 'None'.") + ): + eth_api.build_transaction( + contract_instance=contract_instance, + method_name="dummy_method", + method_args=None, + tx_args={}, + ) + with pytest.raises( + ValueError, match=re.escape("Argument 'tx_args' cannot be 'None'.") + ): + eth_api.build_transaction( + contract_instance=contract_instance, + method_name="dummy_method", + method_args={}, + tx_args=None, + ) + with mock.patch( "web3.eth.Eth.get_transaction_count", return_value=0, diff --git a/plugins/aea-ledger-ethereum/tests/test_ethereum_contract.py b/plugins/aea-ledger-ethereum/tests/test_ethereum_contract.py index 21cb703a5d..a917c01b55 100644 --- a/plugins/aea-ledger-ethereum/tests/test_ethereum_contract.py +++ b/plugins/aea-ledger-ethereum/tests/test_ethereum_contract.py @@ -41,14 +41,14 @@ def test_get_contract_instance(ethereum_testnet_config, ganache): tx = ethereum_api.get_deploy_transaction( contract_interface, ec.address, - 0, + value=0, max_priority_fee_per_gas=1000000000, max_fee_per_gas=1000000000, ) tx = ethereum_api.get_deploy_transaction( contract_interface, ec.address, - 0, + value=0, gas=1000000, max_priority_fee_per_gas=1000000000, max_fee_per_gas=1000000000, @@ -83,7 +83,7 @@ def test_gas_station_strategy(ethereum_testnet_config, ganache): full_path = Path(ROOT_DIR, "tests", "data", "dummy_contract", "build", "some.json") contract_interface = ethereum_api.load_contract_interface(full_path) tx = ethereum_api.get_deploy_transaction( - contract_interface, ec.address, 0, gas_price_strategy="gas_station" + contract_interface, ec.address, value=0, gas_price_strategy="gas_station" ) assert all( [ @@ -104,7 +104,7 @@ def test_eip1559_strategy(ethereum_testnet_config, ganache): full_path = Path(ROOT_DIR, "tests", "data", "dummy_contract", "build", "some.json") contract_interface = ethereum_api.load_contract_interface(full_path) tx = ethereum_api.get_deploy_transaction( - contract_interface, ec.address, 0, gas_price_strategy="eip1559" + contract_interface, ec.address, value=0, gas_price_strategy="eip1559" ) logging.info(tx.keys()) assert all( @@ -117,7 +117,6 @@ def test_eip1559_strategy(ethereum_testnet_config, ganache): "nonce", "maxFeePerGas", "maxPriorityFeePerGas", - "baseFee", "data", "from", ] diff --git a/plugins/aea-ledger-fetchai/aea_ledger_fetchai/_cosmos.py b/plugins/aea-ledger-fetchai/aea_ledger_fetchai/_cosmos.py index 5519d3d7da..b059846ec9 100644 --- a/plugins/aea-ledger-fetchai/aea_ledger_fetchai/_cosmos.py +++ b/plugins/aea-ledger-fetchai/aea_ledger_fetchai/_cosmos.py @@ -263,7 +263,7 @@ def get_event_attributes(tx_receipt: JSONLike) -> Dict: """ return { i["key"]: i["value"] - for i in chain(*[i["attributes"] for i in tx_receipt["logs"][0]["events"]]) + for i in chain(*[i["attributes"] for i in tx_receipt["logs"][0]["events"]]) # type: ignore } @classmethod @@ -1307,7 +1307,7 @@ def _get_transaction( ) # Get account and signer info for each sender - signer_infos: List[SignerInfo] = [] + signer_infos: List[SignerInfo] = [] # type: ignore sign_data: JSONLike = {} for from_address, pub_key, sequence, account_number in zip( from_addresses, pub_keys, sequences, account_numbers diff --git a/scripts/RELEASE_PROCESS.md b/scripts/RELEASE_PROCESS.md index 48f9148fe0..52b6f36f6a 100644 --- a/scripts/RELEASE_PROCESS.md +++ b/scripts/RELEASE_PROCESS.md @@ -40,9 +40,9 @@ 18. Publish the latest packages to the IPFS registry using `aea init --reset --author valory --ipfs --remote` and `aea push-all`. If necessary, run it several times until all packages are updated. -19. Build the release images using `skaffold build -p release` which will also publish them on docker. This builds with no cache so to ensure replicable builds. Before running it, copy packages: `cp -R packages/ deploy-image/packages/` +19. Build the release images using `skaffold build -p release` which will also publish them to Docker Hub. This builds with no cache so to ensure replicable builds. -20. Tag the latest images using `skaffold build -p release-latest` which will also publish them on docker. +20. Tag the latest images using `skaffold build -p release-latest` which will also publish them to Docker Hub. If something goes wrong and only needs a small fix do `LAST_VERSION.post1` as version, apply fixes, push again to PyPI. diff --git a/scripts/publish_packages_to_local_registry.py b/scripts/publish_packages_to_local_registry.py index ef36e2268c..37d0b71e78 100644 --- a/scripts/publish_packages_to_local_registry.py +++ b/scripts/publish_packages_to_local_registry.py @@ -55,7 +55,9 @@ def main() -> None: ipfs_tool = IPFSTool(addr="/ip4/127.0.0.1/tcp/5001/http") with IPFSDaemon(): for package_path in packages: - register_package(ipfs_tool=ipfs_tool, dir_path=package_path, no_pin=False) + register_package( + ipfs_tool=ipfs_tool, dir_path=str(package_path), no_pin=False + ) print("Done!") diff --git a/setup.cfg b/setup.cfg index aade6db38f..f45fda84dd 100644 --- a/setup.cfg +++ b/setup.cfg @@ -279,6 +279,18 @@ ignore_missing_imports = True [mypy-multihash.*] ignore_missing_imports = True +[mypy-Crypto.*] +ignore_missing_imports = True + +[mypy-eth_typing.*] +ignore_missing_imports = True + +[mypy-bech32.*] +ignore_missing_imports = True + +[mypy-eth_utils.*] +ignore_missing_imports = True + [darglint] docstring_style=sphinx strictness=short diff --git a/tox.ini b/tox.ini index d3aae3d0fe..a9814fb542 100644 --- a/tox.ini +++ b/tox.ini @@ -6,8 +6,9 @@ ; we set the associated flag (e.g. for linting we don't need ; the package installation). [tox] -envlist = bandit, black, black-check, isort, isort-check, copyright_check, docs, flake8, liccheck, mypy, py{3.7,3.8,3.9,3.10}, dependencies_check, plugins_deps - +envlist = bandit, safety, black, black-check, isort, isort-check, fix-copyright, check-copyright, hash-check, docs, flake8, liccheck, mypy, pylint, vulture, {plugins-,}py{3.7,3.8,3.9,3.10,3.10-cov}, dependencies-check, package-version-checks, package-dependencies-checks, plugins_deps, fix-doc-hashes, check-doc-links-hashes, check-generate-all-protocols, spell-check, generate-api-documentation +; when running locally we don't want to fail for no good reason +skip_missing_interpreters = true [testenv] basepython = python3.10 @@ -47,7 +48,6 @@ deps = pycryptodome>=3.10.1 cosmpy>=0.4.1,<0.5.0 setuptools==59.6.0 - commands = ; for some reason tox installs aea without respect to the dependencies version specified in seetup.py. at least in CI env ; so install current aea in a normal way @@ -143,7 +143,7 @@ skip_install = True deps = commands = {toxinidir}/scripts/check_copyright_notice.py --check -[testenv:hash_check] +[testenv:hash-check] skipsdist = True usedevelop = True deps = @@ -152,13 +152,13 @@ commands = python -m aea.cli hash all --check python -m aea.cli hash all --packages-dir=./tests/data/packages --check -[testenv:package_version_checks] +[testenv:package-version-checks] skipsdist = True usedevelop = True deps = commands = {toxinidir}/scripts/check_package_versions_in_docs.py -[testenv:package_dependencies_checks] +[testenv:package-dependencies-checks] skipsdist = True usedevelop = True deps = @@ -218,8 +218,8 @@ skip_install = True deps = mypy==0.910 commands = mypy aea packages --disallow-untyped-defs - mypy benchmark examples --check-untyped-defs - mypy scripts tests + mypy benchmark examples --disallow-untyped-defs + mypy scripts tests plugins/aea-ledger-fetchai/aea_ledger_fetchai plugins/aea-ledger-ethereum/aea_ledger_ethereum plugins/aea-ledger-cosmos/aea_ledger_cosmos plugins/aea-cli-ipfs/aea_cli_ipfs [testenv:pylint] whitelist_externals = @@ -231,7 +231,6 @@ deps = pytest==7.0.0 gitpython>=3.1.14 protobuf==3.19.4 - commands = python -m pip install --no-deps file://{toxinidir}/plugins/aea-ledger-ethereum python -m pip install --no-deps file://{toxinidir}/plugins/aea-ledger-cosmos @@ -260,7 +259,14 @@ deps = darglint==1.8.0 commands = darglint aea benchmark examples libs packages plugins scripts -[testenv:check_doc_links_hashes] +[testenv:fix-doc-hashes] +skipsdist = True +usedevelop = True +deps = + PyYAML==5.4.1 +commands = python {toxinidir}/scripts/check_doc_ipfs_hashes.py --fix + +[testenv:check-doc-links-hashes] skipsdist = True usedevelop = True deps = @@ -269,14 +275,14 @@ commands = python {toxinidir}/scripts/check_doc_links.py python {toxinidir}/scripts/check_doc_ipfs_hashes.py python {toxinidir}/scripts/check_ipfs_hashes_pushed.py -[testenv:check_api_docs] +[testenv:check-api-docs] skipsdist = True usedevelop = True deps = pydoc-markdown==4.6.3 commands = {toxinidir}/scripts/generate_api_docs.py --check-clean -[testenv:check_generate_all_protocols] +[testenv:check-generate-all-protocols] skipsdist = True usedevelop = True deps = @@ -286,14 +292,14 @@ deps = isort==5.7.0 commands = python -m aea.cli generate-all-protocols --check-clean -[testenv:spell_check] +[testenv:spell-check] +whitelist_externals = mdspell skipsdist = True usedevelop = True deps = -commands = {toxinidir}/scripts/spell-check.sh - +commands = mdspell -r -n -a --en-gb '**/*.md' '!docker-images/*.md' '!docs/api/**/*.md' -[testenv:dependencies_check] +[testenv:dependencies-check] skipsdist = True skip_install = True commands = @@ -301,7 +307,6 @@ commands = pip uninstall open-aea -y python {toxinidir}/scripts/check_imports_and_dependencies.py - [testenv:plugins_env] skipsdist = True skip_install = True @@ -313,7 +318,6 @@ commands = - /bin/sh -c "rm -fr ./*private_key.txt" {posargs} - [testenv_multi] basepython = python3 whitelist_externals = /bin/sh @@ -352,7 +356,6 @@ deps = pycryptodome>=3.10.1 cosmpy>=0.4.1,<0.5.0 setuptools==59.6.0 - commands = ; for some reason tox installs aea without respect to the dependencies version specified in seetup.py. at least in CI env ; so install current aea in a normal way @@ -392,4 +395,10 @@ commands = {[plugins]commands} [testenv:plugins-py3.9] basepython = python3.9 deps = {[testenv_multi]deps} -commands = {[plugins]commands} \ No newline at end of file +commands = {[plugins]commands} + +[testenv:generate-api-documentation] +usedevelop = True +deps = + pydoc-markdown==4.6.3 +commands = {toxinidir}/scripts/generate_api_docs.py