From fbe0817550dde22c9d39b7716f3f4b56e7b8d4de Mon Sep 17 00:00:00 2001 From: Aristotelis Date: Tue, 15 Oct 2019 15:49:48 +0100 Subject: [PATCH 01/15] 95% coverage -> crypto/base.py --- tests/test_crypto/test_crypto.py | 38 +++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/tests/test_crypto/test_crypto.py b/tests/test_crypto/test_crypto.py index 2b38890db1..c4a04b7ab3 100644 --- a/tests/test_crypto/test_crypto.py +++ b/tests/test_crypto/test_crypto.py @@ -18,23 +18,41 @@ # ------------------------------------------------------------------------------ """This module contains the tests of the crypto module.""" +from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat -from cryptography.hazmat.backends import default_backend -from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat, \ - load_pem_private_key - -from aea.crypto.base import DefaultCrypto +from aea.crypto.base import DefaultCrypto, _load_pem_private_key_from_path from ..conftest import ROOT_DIR +from pathlib import Path -def test_initialization_from_existing_private_key(): - """Test that the initialization from an existing private key works correctly.""" - private_key_pem_path = ROOT_DIR + "/tests/data/priv.pem" +PRIVATE_KEY_PEM_PATH = ROOT_DIR + "/tests/data/priv.pem" - private_key = load_pem_private_key(open(private_key_pem_path, "rb").read(), None, default_backend()) - c = DefaultCrypto(private_key_pem_path=private_key_pem_path) +def test_initialization_from_existing_private_key(): + """Test that the initialization from an existing private key works correctly.""" + path = Path(PRIVATE_KEY_PEM_PATH) + private_key = _load_pem_private_key_from_path(path=path) + assert private_key is not None, "The private key is not None after the loading!" + c = DefaultCrypto(private_key_pem_path=PRIVATE_KEY_PEM_PATH) expected_public_key = private_key.public_key().public_bytes(encoding=Encoding.PEM, format=PublicFormat.SubjectPublicKeyInfo) actual_public_key = c.public_key_pem assert expected_public_key == actual_public_key + + +def test_return_fingerprint(): + """Test that the fingerprint is not None.""" + c = DefaultCrypto(private_key_pem_path=PRIVATE_KEY_PEM_PATH) + assert c.fingerprint is not None, "The fingerprint must be None" + + +def test_sign_data(): + """Test the sign message and the verification of the message.""" + c = DefaultCrypto(private_key_pem_path=PRIVATE_KEY_PEM_PATH) + my_signature = c.sign_data(b"Hello") + assert len(my_signature) > 0, "Signed data must not be none" + assert c.is_confirmed_integrity(b"Hello", my_signature, c.public_key), "The verification must be True" + obj = DefaultCrypto(private_key_pem_path=PRIVATE_KEY_PEM_PATH) + + # TODO: I am not sure about this :) + assert type(obj._pvk_obj_to_pem(obj._private_key)) == bytes, "Must return the bytes for the .pem file!" From b55786bb5ebf8cd8e30d732fa2682f6a97eeeb3c Mon Sep 17 00:00:00 2001 From: MarcoFavorito Date: Fri, 18 Oct 2019 13:07:29 +0200 Subject: [PATCH 02/15] add publish instructions to docker images README --- deploy-image/README.md | 19 +++++++++++++++++++ deploy-image/docker-env.sh | 3 +++ develop-image/README.md | 19 +++++++++++++++++++ develop-image/docker-env.sh | 3 +++ 4 files changed, 44 insertions(+) diff --git a/deploy-image/README.md b/deploy-image/README.md index df3076d28f..f0fdd671a8 100644 --- a/deploy-image/README.md +++ b/deploy-image/README.md @@ -13,5 +13,24 @@ We recommend using the following command for building: docker run --env AGENT_REPO_URL=https://github.com/fetchai/echo_agent.git aea-deploy:latest +## Publish + +First, be sure you tagged the image with the `latest` tag: + + docker tag aea-deploy: aea-deploy:latest + +Then, publish the images. First, the `aea-deploy:` + + ./develop-image/scripts/docker-publish-img.sh + +And then, the `aea-deploy:latest` image: + +- In `docker-env.sh`, uncomment `DOCKER_IMAGE_TAG=aea-deploy:latest` + +- Run the publish command again: + + ./develop-image/scripts/docker-publish-img.sh + + ## TODO We need to add support for setting the connection endpoints for OEF/Ledger so they can be used a deploytime. I would suggest these are set as environment variables if possible. diff --git a/deploy-image/docker-env.sh b/deploy-image/docker-env.sh index 5050b3df09..dc61a6ee56 100755 --- a/deploy-image/docker-env.sh +++ b/deploy-image/docker-env.sh @@ -1,5 +1,8 @@ #!/bin/bash +# Swap the following lines if you want to work with 'latest' DOCKER_IMAGE_TAG=aea-deploy:0.1.8 +# DOCKER_IMAGE_TAG=aea-deploy:latest + DOCKER_BUILD_CONTEXT_DIR=.. DOCKERFILE=./Dockerfile diff --git a/develop-image/README.md b/develop-image/README.md index e32e4ec717..1a133baf29 100644 --- a/develop-image/README.md +++ b/develop-image/README.md @@ -23,3 +23,22 @@ E.g.: As before, to pass params to the `docker run` command: ./develop-image/scripts/docker-run.sh -p 8080:80 -- /bin/bash + + +## Publish + +First, be sure you tagged the image with the `latest` tag: + + docker tag aea-develop: aea-develop:latest + +Then, publish the images. First, the `aea-develop:` + + ./develop-image/scripts/docker-publish-img.sh + +And then, the `aea-develop:latest` image: + +- In `docker-env.sh`, uncomment `DOCKER_IMAGE_TAG=aea-develop:latest` + +- Run the publish command again: + + ./develop-image/scripts/docker-publish-img.sh diff --git a/develop-image/docker-env.sh b/develop-image/docker-env.sh index d60a4e7601..e9d1c10396 100755 --- a/develop-image/docker-env.sh +++ b/develop-image/docker-env.sh @@ -1,5 +1,8 @@ #!/bin/bash +# Swap the following lines if you want to work with 'latest' DOCKER_IMAGE_TAG=aea-develop:0.1.8 +# DOCKER_IMAGE_TAG=aea-develop:latest + DOCKER_BUILD_CONTEXT_DIR=.. DOCKERFILE=./Dockerfile From 6e02ab6bfffea64609ecb79aeadd3e72accf5fc1 Mon Sep 17 00:00:00 2001 From: MarcoFavorito Date: Fri, 18 Oct 2019 13:07:55 +0200 Subject: [PATCH 03/15] update PR release template, links to images' READMEs. --- .github/pull_request_template.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 51cdf740a3..5da53d0d4c 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -53,7 +53,9 @@ _Put an `x` in the boxes that apply._ - [ ] I built the documentation and updated it with the latest changes - [ ] I've added an item in `HISTORY.rst` for this release - [ ] I bumped the version number in the `aea/__version__.py` file. -- [ ] I bumped the version number in every Docker image of the repo and published it. Also, I built and published them with tag `latest` +- [ ] I bumped the version number in every Docker image of the repo and published it. Also, I built and published them with tag `latest` + (check the READMEs of [`aea-develop`](../develop-image/README.md#publish) + and [`aea-deploy`](../deploy-image/README.md#publish)) - [ ] I have checked that the documentation about the `aea cli` tool works ## Further comments From bdc152877da18df205afdf4468aa6eee1c887332 Mon Sep 17 00:00:00 2001 From: MarcoFavorito Date: Fri, 18 Oct 2019 13:15:42 +0200 Subject: [PATCH 04/15] add instructions for Docker installation in quickstart preliminaries. --- docs/quickstart.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/quickstart.md b/docs/quickstart.md index f74c9e794f..eb08c19907 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -24,6 +24,12 @@ touch Pipfile && pipenv --python 3.7 && pipenv shell ``` +At some point, you will need [Docker](https://www.docker.com/) installed on your machine +(e.g. to run an OEF Node). + +If you don't have it, please check the official documentation [here](https://docs.docker.com/install/) +and follow the instructions for your platform. + ## Installation Install the Autonomous Economic Agent framework. From f7ed68eef9ff35b59c2317f492d5d8042fbed936 Mon Sep 17 00:00:00 2001 From: Diarmid Campbell Date: Fri, 18 Oct 2019 13:34:56 +0100 Subject: [PATCH 05/15] gui now lists all skills, connections and protocols from aea in virtual env as wel as grom packge registry dir --- aea/cli_gui/__init__.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/aea/cli_gui/__init__.py b/aea/cli_gui/__init__.py index bcaea9821c..2fd2b2a791 100644 --- a/aea/cli_gui/__init__.py +++ b/aea/cli_gui/__init__.py @@ -101,19 +101,22 @@ def get_agents(): return agent_list -def get_registered_items(item_type): - """Return list of all protocols, connections or skills in the registry.""" - item_dir = os.path.join(flask.app.agents_dir, "packages/" + item_type + "s") - +def _add_items(item_dir, item_type, items_list): file_list = glob.glob(os.path.join(item_dir, '*')) - - items_list = [] - for path in file_list: if is_item_dir(path, item_type): head, tail = os.path.split(path) desc = read_description(path, item_type) - items_list.append({"id": tail, "description": desc}) + if not {"id": tail, "description": desc} in items_list: + items_list.append({"id": tail, "description": desc}) + + +def get_registered_items(item_type): + """Return list of all protocols, connections or skills in the registry.""" + items_list = [] + + _add_items(os.path.join(flask.app.agents_dir, "packages/" + item_type + "s"), item_type, items_list) + _add_items(os.path.join(flask.app.module_dir, "aea/" + item_type + "s"), item_type, items_list) return items_list From 826db99132e9ad4a6ef7e29dbc1c2bb9f4f6e2e0 Mon Sep 17 00:00:00 2001 From: David Minarsch Date: Fri, 18 Oct 2019 15:48:24 +0200 Subject: [PATCH 06/15] Fix the connexion depenceny and bump its version --- Pipfile | 2 +- Pipfile.lock | 112 +++++++++++++++++++++++++++--------------------- docs/cli-gui.md | 8 +++- setup.py | 2 +- 4 files changed, 73 insertions(+), 51 deletions(-) diff --git a/Pipfile b/Pipfile index 3cc92f43a0..3815b5eb49 100644 --- a/Pipfile +++ b/Pipfile @@ -33,7 +33,7 @@ colorlog = "*" jsonschema = "*" protobuf = "*" flask = "*" -connexion = {git = "https://github.com/neverpanic/connexion.git",editable = true,ref = "jsonschema-3"} +connexion = ">=2.4.0" watchdog = "*" python-dotenv = "*" fetchai-ledger-api = "*" diff --git a/Pipfile.lock b/Pipfile.lock index 26fa2b2a07..00ec23c1cd 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "eeff9998b99b29ddb9eafda38d9f37c6493fc54c6a63333cdb8945c31e7f30f9" + "sha256": "538f6a0573e14e00ff12b0989c0499023dfd326a3ce9c48ddb00ed3fc6d2f916" }, "pipfile-spec": 6, "requires": { @@ -28,13 +28,6 @@ ], "version": "==0.26.2" }, - "asn1crypto": { - "hashes": [ - "sha256:5abe83e773026162e4869f4ac16edf7554f661e8cc0bb6d2be3bc6915456731b", - "sha256:8f3f9470d4ba7aa53afb00278dc26aac22dc3a0d4ed1335fd772f034e094401e" - ], - "version": "==1.1.0" - }, "attrdict": { "hashes": [ "sha256:35c90698b55c683946091177177a9e9c0713a0860f0e049febd72649ccd77b70", @@ -67,6 +60,7 @@ }, "cffi": { "hashes": [ + "sha256:08f99e8b38d5134d504aa7e486af8e4fde66a2f388bbecc270cdd1e00fa09ff8", "sha256:1112d2fc92a867a6103bce6740a549e74b1d320cf28875609f6e93857eee4f2d", "sha256:1b9ab50c74e075bd2ae489853c5f7f592160b379df53b7f72befcbe145475a36", "sha256:24eff2997436b6156c2f30bed215c782b1d8fd8c6a704206053c79af95962e45", @@ -74,6 +68,9 @@ "sha256:362e896cea1249ed5c2a81cf6477fabd9e1a5088aa7ea08358a4c6b0998294d2", "sha256:40eddb3589f382cb950f2dcf1c39c9b8d7bd5af20665ce273815b0d24635008b", "sha256:5ed40760976f6b8613d4a0db5e423673ca162d4ed6c9ed92d1f4e58a47ee01b5", + "sha256:632c6112c1e914c486f06cfe3f0cc507f44aa1e00ebf732cedb5719e6aa0466a", + "sha256:64d84f0145e181f4e6cc942088603c8db3ae23485c37eeda71cb3900b5e67cb4", + "sha256:6cb4edcf87d0e7f5bdc7e5c1a0756fbb37081b2181293c5fdf203347df1cd2a2", "sha256:6f19c9df4785305669335b934c852133faed913c0faa63056248168966f7a7d5", "sha256:719537b4c5cd5218f0f47826dd705fb7a21d83824920088c4214794457113f3f", "sha256:7b0e337a70e58f1a36fb483fd63880c9e74f1db5c532b4082bceac83df1523fa", @@ -82,10 +79,12 @@ "sha256:8978115c6f0b0ce5880bc21c967c65058be8a15f1b81aa5fdbdcbea0e03952d1", "sha256:8f7eec920bc83692231d7306b3e311586c2e340db2dc734c43c37fbf9c981d24", "sha256:8fe230f612c18af1df6f348d02d682fe2c28ca0a6c3856c99599cdacae7cf226", + "sha256:92068ebc494b5f9826b822cec6569f1f47b9a446a3fef477e1d11d7fac9ea895", "sha256:b57e1c8bcdd7340e9c9d09613b5e7fdd0c600be142f04e2cc1cc8cb7c0b43529", "sha256:ba956c9b44646bc1852db715b4a252e52a8f5a4009b57f1dac48ba3203a7bde1", "sha256:ca42034c11eb447497ea0e7b855d87ccc2aebc1e253c22e7d276b8599c112a27", "sha256:dc9b2003e9a62bbe0c84a04c61b0329e86fccd85134a78d7aca373bbbf788165", + "sha256:dd308802beb4b2961af8f037becbdf01a1e85009fdfc14088614c1b3c383fae5", "sha256:e77cd105b19b8cd721d101687fcf665fd1553eb7b57556a1ef0d453b6fc42faa", "sha256:f56dff1bd81022f1c980754ec721fb8da56192b026f17f0f99b965da5ab4fbd2", "sha256:fa4cc13c03ea1d0d37ce8528e0ecc988d2365e8ac64d8d86cafab4038cb4ce89", @@ -127,31 +126,39 @@ "version": "==4.0.2" }, "connexion": { - "editable": true, - "git": "https://github.com/neverpanic/connexion.git", - "ref": "2f0d92b5765196f7229d1b7ef4db9d97d8476676" + "hashes": [ + "sha256:6e0569b646f2e6229923dc4e4c6e0325e223978bd19105779fd81e16bcb22fdf", + "sha256:7b4268e9ea837241e530738b35040345b78c8748d05d2c22805350aca0cd5b1c" + ], + "index": "pypi", + "version": "==2.4.0" }, "cryptography": { "hashes": [ - "sha256:24b61e5fcb506424d3ec4e18bca995833839bf13c59fc43e530e488f28d46b8c", - "sha256:25dd1581a183e9e7a806fe0543f485103232f940fcfc301db65e630512cce643", - "sha256:3452bba7c21c69f2df772762be0066c7ed5dc65df494a1d53a58b683a83e1216", - "sha256:41a0be220dd1ed9e998f5891948306eb8c812b512dc398e5a01846d855050799", - "sha256:5751d8a11b956fbfa314f6553d186b94aa70fdb03d8a4d4f1c82dcacf0cbe28a", - "sha256:5f61c7d749048fa6e3322258b4263463bfccefecb0dd731b6561cb617a1d9bb9", - "sha256:72e24c521fa2106f19623a3851e9f89ddfdeb9ac63871c7643790f872a305dfc", - "sha256:7b97ae6ef5cba2e3bb14256625423413d5ce8d1abb91d4f29b6d1a081da765f8", - "sha256:961e886d8a3590fd2c723cf07be14e2a91cf53c25f02435c04d39e90780e3b53", - "sha256:96d8473848e984184b6728e2c9d391482008646276c3ff084a1bd89e15ff53a1", - "sha256:ae536da50c7ad1e002c3eee101871d93abdc90d9c5f651818450a0d3af718609", - "sha256:b0db0cecf396033abb4a93c95d1602f268b3a68bb0a9cc06a7cff587bb9a7292", - "sha256:cfee9164954c186b191b91d4193989ca994703b2fff406f71cf454a2d3c7327e", - "sha256:e6347742ac8f35ded4a46ff835c60e68c22a536a8ae5c4422966d06946b6d4c6", - "sha256:f27d93f0139a3c056172ebb5d4f9056e770fdf0206c2f422ff2ebbad142e09ed", - "sha256:f57b76e46a58b63d1c6375017f4564a28f19a5ca912691fd2e4261b3414b618d" + "sha256:02079a6addc7b5140ba0825f542c0869ff4df9a69c360e339ecead5baefa843c", + "sha256:1df22371fbf2004c6f64e927668734070a8953362cd8370ddd336774d6743595", + "sha256:369d2346db5934345787451504853ad9d342d7f721ae82d098083e1f49a582ad", + "sha256:3cda1f0ed8747339bbdf71b9f38ca74c7b592f24f65cdb3ab3765e4b02871651", + "sha256:44ff04138935882fef7c686878e1c8fd80a723161ad6a98da31e14b7553170c2", + "sha256:4b1030728872c59687badcca1e225a9103440e467c17d6d1730ab3d2d64bfeff", + "sha256:58363dbd966afb4f89b3b11dfb8ff200058fbc3b947507675c19ceb46104b48d", + "sha256:6ec280fb24d27e3d97aa731e16207d58bd8ae94ef6eab97249a2afe4ba643d42", + "sha256:7270a6c29199adc1297776937a05b59720e8a782531f1f122f2eb8467f9aab4d", + "sha256:73fd30c57fa2d0a1d7a49c561c40c2f79c7d6c374cc7750e9ac7c99176f6428e", + "sha256:7f09806ed4fbea8f51585231ba742b58cbcfbfe823ea197d8c89a5e433c7e912", + "sha256:90df0cc93e1f8d2fba8365fb59a858f51a11a394d64dbf3ef844f783844cc793", + "sha256:971221ed40f058f5662a604bd1ae6e4521d84e6cad0b7b170564cc34169c8f13", + "sha256:a518c153a2b5ed6b8cc03f7ae79d5ffad7315ad4569b2d5333a13c38d64bd8d7", + "sha256:b0de590a8b0979649ebeef8bb9f54394d3a41f66c5584fff4220901739b6b2f0", + "sha256:b43f53f29816ba1db8525f006fa6f49292e9b029554b3eb56a189a70f2a40879", + "sha256:d31402aad60ed889c7e57934a03477b572a03af7794fa8fb1780f21ea8f6551f", + "sha256:de96157ec73458a7f14e3d26f17f8128c959084931e8997b9e655a39c8fde9f9", + "sha256:df6b4dca2e11865e6cfbfb708e800efb18370f5a46fd601d3755bc7f85b3a8a2", + "sha256:ecadccc7ba52193963c0475ac9f6fa28ac01e01349a2ca48509667ef41ffd2cf", + "sha256:fb81c17e0ebe3358486cd8cc3ad78adbae58af12fc2bf2bc0bb84e8090fa5ce8" ], "index": "pypi", - "version": "==2.7" + "version": "==2.8" }, "cytoolz": { "hashes": [ @@ -573,11 +580,11 @@ }, "web3": { "hashes": [ - "sha256:5d1d301da95b29e2d515ec4139dfd77d8edee127fa238800489a5e2f877314a4", - "sha256:812b753fc09a6d675acbadf437447d4cfdbfb7290ac6203f2cc06fc80080e0b5" + "sha256:a6bbf8090fd880be1a736872bf42163b44a56691d97b7e139d7f16247c1d7f8d", + "sha256:c0e070670a7d8c6ed4b8585347fec79a924c01520362ba41b411a5d0a9c8e6f9" ], "index": "pypi", - "version": "==5.2.0" + "version": "==5.2.1" }, "websocket-client": { "hashes": [ @@ -837,26 +844,30 @@ }, "mypy": { "hashes": [ - "sha256:1d98fd818ad3128a5408148c9e4a5edce6ed6b58cc314283e631dd5d9216527b", - "sha256:22ee018e8fc212fe601aba65d3699689dd29a26410ef0d2cc1943de7bec7e3ac", - "sha256:3a24f80776edc706ec8d05329e854d5b9e464cd332e25cde10c8da2da0a0db6c", - "sha256:42a78944e80770f21609f504ca6c8173f7768043205b5ac51c9144e057dcf879", - "sha256:4b2b20106973548975f0c0b1112eceb4d77ed0cafe0a231a1318f3b3a22fc795", - "sha256:591a9625b4d285f3ba69f541c84c0ad9e7bffa7794da3fa0585ef13cf95cb021", - "sha256:5b4b70da3d8bae73b908a90bb2c387b977e59d484d22c604a2131f6f4397c1a3", - "sha256:84edda1ffeda0941b2ab38ecf49302326df79947fa33d98cdcfbf8ca9cf0bb23", - "sha256:b2b83d29babd61b876ae375786960a5374bba0e4aba3c293328ca6ca5dc448dd", - "sha256:cc4502f84c37223a1a5ab700649b5ab1b5e4d2bf2d426907161f20672a21930b", - "sha256:e29e24dd6e7f39f200a5bb55dcaa645d38a397dd5a6674f6042ef02df5795046" + "sha256:1521c186a3d200c399bd5573c828ea2db1362af7209b2adb1bb8532cea2fb36f", + "sha256:31a046ab040a84a0fc38bc93694876398e62bc9f35eca8ccbf6418b7297f4c00", + "sha256:3b1a411909c84b2ae9b8283b58b48541654b918e8513c20a400bb946aa9111ae", + "sha256:48c8bc99380575deb39f5d3400ebb6a8a1cb5cc669bbba4d3bb30f904e0a0e7d", + "sha256:540c9caa57a22d0d5d3c69047cc9dd0094d49782603eb03069821b41f9e970e9", + "sha256:672e418425d957e276c291930a3921b4a6413204f53fe7c37cad7bc57b9a3391", + "sha256:6ed3b9b3fdc7193ea7aca6f3c20549b377a56f28769783a8f27191903a54170f", + "sha256:9371290aa2cad5ad133e4cdc43892778efd13293406f7340b9ffe99d5ec7c1d9", + "sha256:ace6ac1d0f87d4072f05b5468a084a45b4eda970e4d26704f201e06d47ab2990", + "sha256:b428f883d2b3fe1d052c630642cc6afddd07d5cd7873da948644508be3b9d4a7", + "sha256:d5bf0e6ec8ba346a2cf35cb55bf4adfddbc6b6576fcc9e10863daa523e418dbb", + "sha256:d7574e283f83c08501607586b3167728c58e8442947e027d2d4c7dcd6d82f453", + "sha256:dc889c84241a857c263a2b1cd1121507db7d5b5f5e87e77147097230f374d10b", + "sha256:f4748697b349f373002656bf32fede706a0e713d67bfdcf04edf39b1f61d46eb" ], "index": "pypi", - "version": "==0.730" + "version": "==0.740" }, "mypy-extensions": { "hashes": [ - "sha256:a161e3b917053de87dbe469987e173e49fb454eca10ef28b48b384538cc11458" + "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d", + "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8" ], - "version": "==0.4.2" + "version": "==0.4.3" }, "packaging": { "hashes": [ @@ -1030,20 +1041,25 @@ }, "typed-ast": { "hashes": [ + "sha256:1170afa46a3799e18b4c977777ce137bb53c7485379d9706af8a59f2ea1aa161", "sha256:18511a0b3e7922276346bcb47e2ef9f38fb90fd31cb9223eed42c85d1312344e", "sha256:262c247a82d005e43b5b7f69aff746370538e176131c32dda9cb0f324d27141e", "sha256:2b907eb046d049bcd9892e3076c7a6456c93a25bebfe554e931620c90e6a25b0", "sha256:354c16e5babd09f5cb0ee000d54cfa38401d8b8891eefa878ac772f827181a3c", + "sha256:48e5b1e71f25cfdef98b013263a88d7145879fbb2d5185f2a0c79fa7ebbeae47", "sha256:4e0b70c6fc4d010f8107726af5fd37921b666f5b31d9331f0bd24ad9a088e631", "sha256:630968c5cdee51a11c05a30453f8cd65e0cc1d2ad0d9192819df9978984529f4", "sha256:66480f95b8167c9c5c5c87f32cf437d585937970f3fc24386f313a4c97b44e34", "sha256:71211d26ffd12d63a83e079ff258ac9d56a1376a25bc80b1cdcdf601b855b90b", + "sha256:7954560051331d003b4e2b3eb822d9dd2e376fa4f6d98fee32f452f52dd6ebb2", + "sha256:838997f4310012cf2e1ad3803bce2f3402e9ffb71ded61b5ee22617b3a7f6b6e", "sha256:95bd11af7eafc16e829af2d3df510cecfd4387f6453355188342c3e79a2ec87a", "sha256:bc6c7d3fa1325a0c6613512a093bc2a2a15aeec350451cbdf9e1d4bffe3e3233", "sha256:cc34a6f5b426748a507dd5d1de4c1978f2eb5626d51326e43280941206c209e1", "sha256:d755f03c1e4a51e9b24d899561fec4ccaf51f210d52abdf8c07ee2849b212a36", "sha256:d7c45933b1bdfaf9f36c579671fec15d25b06c8398f113dab64c18ed1adda01d", "sha256:d896919306dd0aa22d0132f62a1b78d11aaf4c9fc5b3410d3c666b818191630a", + "sha256:fdc1c9bbf79510b76408840e009ed65958feba92a88833cdceecff93ae8fff66", "sha256:ffde2fbfad571af120fcbfbbc61c72469e72f550d676c3342492a9dfdefb8f12" ], "version": "==1.4.0" @@ -1058,10 +1074,10 @@ }, "virtualenv": { "hashes": [ - "sha256:680af46846662bb38c5504b78bad9ed9e4f3ba2d54f54ba42494fdf94337fe30", - "sha256:f78d81b62d3147396ac33fc9d77579ddc42cc2a98dd9ea38886f616b33bc7fb2" + "sha256:3e3597e89c73df9313f5566e8fc582bd7037938d15b05329c232ec57a11a7ad5", + "sha256:5d370508bf32e522d79096e8cbea3499d47e624ac7e11e9089f9397a0b3318df" ], - "version": "==16.7.5" + "version": "==16.7.6" }, "virtualenv-clone": { "hashes": [ diff --git a/docs/cli-gui.md b/docs/cli-gui.md index 991663195e..9718319ce3 100644 --- a/docs/cli-gui.md +++ b/docs/cli-gui.md @@ -4,7 +4,13 @@ These instructions will take you through building an agent, starting an OEF Node ## Preliminaries -Ensure you have the framework installed and the CLI is working by following the [quick-start guide](quickstart.md). +Ensure you have the framework installed and the CLI is working by following the [quick-start guide](quickstart.md). + +Please install the extra dependencies for the CLI GUI: + ```python + pip install aea[cli_gui] + ``` + ## Starting the GUI Go to your working folder, where you want to create new agents. If you followed the quick start guide, this will be in the my_aea directory. Start the local web-server: diff --git a/setup.py b/setup.py index 78a42e2006..e7dd84caf1 100644 --- a/setup.py +++ b/setup.py @@ -76,7 +76,7 @@ def get_all_extras() -> Dict: cli_gui = [ "flask", - "connexion[swagger-ui] @ git+https://github.com/neverpanic/connexion.git@jsonschema-3#egg=connexion[swagger-ui]", + "connexion[swagger-ui]", *cli_deps ] From 8a9aaa1cc956364d57acbfe1bdadb04935610905 Mon Sep 17 00:00:00 2001 From: MarcoFavorito Date: Fri, 18 Oct 2019 16:34:31 +0200 Subject: [PATCH 07/15] fix path separator in root dir path of schema resolver --- aea/configurations/loader.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/aea/configurations/loader.py b/aea/configurations/loader.py index dd1b1db805..a9c7b2ff2d 100644 --- a/aea/configurations/loader.py +++ b/aea/configurations/loader.py @@ -45,7 +45,8 @@ class ConfigLoader(Generic[T]): def __init__(self, schema_filename: str, configuration_type: Type[T]): """Initialize the parser for configuration files.""" self.schema = json.load(open(os.path.join(_SCHEMAS_DIR, schema_filename))) - self.resolver = jsonschema.RefResolver("file://{}/".format(Path(_SCHEMAS_DIR).absolute()), self.schema) + root_path = "file://{}{}".format(Path(_SCHEMAS_DIR).absolute(), os.path.sep) + self.resolver = jsonschema.RefResolver(root_path, self.schema) self.validator = Draft4Validator(self.schema, resolver=self.resolver) self.configuration_type = configuration_type # type: Type[T] From 2957a4abbc9e900d80e87d26a7e8c36299e9f1cd Mon Sep 17 00:00:00 2001 From: MarcoFavorito Date: Fri, 18 Oct 2019 17:31:34 +0200 Subject: [PATCH 08/15] remove hard-coded path joined in 'setup.py' --- setup.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index e7dd84caf1..3c0ca4a23d 100644 --- a/setup.py +++ b/setup.py @@ -137,7 +137,10 @@ def get_all_extras() -> Dict: zip_safe=False, include_package_data=True, data_files=[ - ("aea/skills/base/schemas/", glob.glob("aea/skills/base/schemas/*.json")), + ( + os.path.join("aea", "skills", "base", "schemas"), + glob.glob(os.path.join("aea", "skills", "base", "schemas", "*.json")) + ), ], license=about['__license__'], ) From 4c05674d4680aa15863935e5d2ada6b5aee81324 Mon Sep 17 00:00:00 2001 From: Aristotelis Date: Fri, 18 Oct 2019 16:48:59 +0100 Subject: [PATCH 09/15] Tests for the local/connection --- aea/connections/base.py | 2 +- aea/connections/local/connection.py | 4 +- .../test_connections/test_local/test_misc.py | 5 +- .../test_local/test_search_services.py | 273 ++++++++++++++---- 4 files changed, 216 insertions(+), 68 deletions(-) diff --git a/aea/connections/base.py b/aea/connections/base.py index 541eb8810d..fdabb359f0 100644 --- a/aea/connections/base.py +++ b/aea/connections/base.py @@ -26,7 +26,7 @@ from aea.configurations.base import ConnectionConfig if TYPE_CHECKING: - from aea.mail.base import Envelope + from aea.mail.base import Envelope # pragma: no cover class Channel(ABC): diff --git a/aea/connections/local/connection.py b/aea/connections/local/connection.py index 2b59091788..a2db07006c 100644 --- a/aea/connections/local/connection.py +++ b/aea/connections/local/connection.py @@ -121,7 +121,7 @@ def handle_agent_message(self, envelope: Envelope) -> None: if destination not in self._queues: msg = OEFMessage(oef_type=OEFMessage.Type.DIALOGUE_ERROR, id=STUB_DIALOGUE_ID, dialogue_id=STUB_DIALOGUE_ID, origin=destination) msg_bytes = OEFSerializer().encode(msg) - error_envelope = Envelope(to=destination, sender=envelope.sender, protocol_id=OEFMessage.protocol_id, message=msg_bytes) + error_envelope = Envelope(to=envelope.sender, sender=DEFAULT_OEF, protocol_id=OEFMessage.protocol_id, message=msg_bytes) self._send(error_envelope) return else: @@ -140,7 +140,7 @@ def register_service(self, public_key: str, service_description: Description): def register_service_wide(self, public_key: str, service_description: Description): """Register service wide.""" - raise NotImplementedError + raise NotImplementedError # pragma: no cover def unregister_service(self, public_key: str, msg_id: int, service_description: Description) -> None: """ diff --git a/tests/test_connections/test_local/test_misc.py b/tests/test_connections/test_local/test_misc.py index 36aca131f6..e9295f79b7 100644 --- a/tests/test_connections/test_local/test_misc.py +++ b/tests/test_connections/test_local/test_misc.py @@ -31,6 +31,10 @@ def test_connection(): """Test that two mailbox can connect to the node.""" node = LocalNode() + + node._queues['m_key'] = "m_key" + assert node.connect("m_key") is None, "The connect function must return None." + mailbox1 = MailBox(OEFLocalConnection("mailbox1", node)) mailbox2 = MailBox(OEFLocalConnection("mailbox2", node)) @@ -97,6 +101,5 @@ def test_communication(): msg = FIPASerializer().decode(envelope.message) assert envelope.protocol_id == "fipa" assert msg.get("performative") == FIPAMessage.Performative.DECLINE - mailbox1.disconnect() mailbox2.disconnect() diff --git a/tests/test_connections/test_local/test_search_services.py b/tests/test_connections/test_local/test_search_services.py index dfcaca957b..b61a2608c1 100644 --- a/tests/test_connections/test_local/test_search_services.py +++ b/tests/test_connections/test_local/test_search_services.py @@ -18,9 +18,13 @@ # ------------------------------------------------------------------------------ """This module contains the tests for the search feature of the local OEF node.""" +import time +import pytest from aea.connections.local.connection import LocalNode, OEFLocalConnection from aea.mail.base import MailBox, Envelope +from aea.protocols.fipa.message import FIPAMessage +from aea.protocols.fipa.serialization import FIPASerializer from aea.protocols.oef.message import OEFMessage from aea.protocols.oef.models import Query, DataModel, Description from aea.protocols.oef.serialization import DEFAULT_OEF, OEFSerializer @@ -47,7 +51,8 @@ def test_empty_search_result(self): # build and send the request search_services_request = OEFMessage(oef_type=OEFMessage.Type.SEARCH_SERVICES, id=request_id, query=query) msg_bytes = OEFSerializer().encode(search_services_request) - envelope = Envelope(to=DEFAULT_OEF, sender=self.public_key_1, protocol_id=OEFMessage.protocol_id, message=msg_bytes) + envelope = Envelope(to=DEFAULT_OEF, sender=self.public_key_1, protocol_id=OEFMessage.protocol_id, + message=msg_bytes) self.mailbox1.send(envelope) # check the result @@ -59,6 +64,21 @@ def test_empty_search_result(self): assert search_result.get("type") == OEFMessage.Type.SEARCH_RESULT assert search_result.get("agents") == [] + # build and send the request + search_agents_request = OEFMessage(oef_type=OEFMessage.Type.SEARCH_AGENTS, id=request_id, query=query) + msg_bytes = OEFSerializer().encode(search_agents_request) + envelope = Envelope(to=DEFAULT_OEF, sender=self.public_key_1, protocol_id=OEFMessage.protocol_id, + message=msg_bytes) + self.mailbox1.send(envelope) + + # check the result + response_envelope = self.mailbox1.inbox.get(block=True, timeout=5.0) + assert response_envelope.protocol_id == OEFMessage.protocol_id + assert response_envelope.sender == DEFAULT_OEF + search_result = OEFSerializer().decode(response_envelope.message) + assert search_result.get("type") == OEFMessage.Type.SEARCH_RESULT + assert search_result.get("agents") == [] + @classmethod def teardown_class(cls): """Teardown the test.""" @@ -83,9 +103,11 @@ def setup_class(cls): service_id = '' cls.data_model = DataModel("foobar", attributes=[]) service_description = Description({"foo": 1, "bar": "baz"}, data_model=cls.data_model) - register_service_request = OEFMessage(oef_type=OEFMessage.Type.REGISTER_SERVICE, id=request_id, service_description=service_description, service_id=service_id) + register_service_request = OEFMessage(oef_type=OEFMessage.Type.REGISTER_SERVICE, id=request_id, + service_description=service_description, service_id=service_id) msg_bytes = OEFSerializer().encode(register_service_request) - envelope = Envelope(to=DEFAULT_OEF, sender=cls.public_key_1, protocol_id=OEFMessage.protocol_id, message=msg_bytes) + envelope = Envelope(to=DEFAULT_OEF, sender=cls.public_key_1, protocol_id=OEFMessage.protocol_id, + message=msg_bytes) cls.mailbox1.send(envelope) def test_not_empty_search_result(self): @@ -96,7 +118,8 @@ def test_not_empty_search_result(self): # build and send the request search_services_request = OEFMessage(oef_type=OEFMessage.Type.SEARCH_SERVICES, id=request_id, query=query) msg_bytes = OEFSerializer().encode(search_services_request) - envelope = Envelope(to=DEFAULT_OEF, sender=self.public_key_1, protocol_id=OEFMessage.protocol_id, message=msg_bytes) + envelope = Envelope(to=DEFAULT_OEF, sender=self.public_key_1, protocol_id=OEFMessage.protocol_id, + message=msg_bytes) self.mailbox1.send(envelope) # check the result @@ -114,63 +137,185 @@ def teardown_class(cls): cls.mailbox1.disconnect() -# class TestFilteredSearchResult: -# """Test that the query system of the search gives the expected result.""" -# -# @classmethod -# def setup_class(cls): -# """Set up the test.""" -# cls.node = LocalNode() -# -# cls.public_key_1 = "mailbox1" -# cls.public_key_2 = "mailbox2" -# cls.mailbox1 = MailBox(OEFLocalConnection(cls.public_key_1, cls.node)) -# cls.mailbox2 = MailBox(OEFLocalConnection(cls.public_key_2, cls.node)) -# cls.mailbox1.connect() -# cls.mailbox2.connect() -# -# # register 'mailbox2' as a service 'foobar'. -# request_id = 1 -# service_id = '' -# cls.data_model_foobar = DataModel("foobar", attributes=[]) -# service_description = Description({"foo": 1, "bar": "baz"}, data_model=cls.data_model_foobar) -# register_service_request = OEFMessage(oef_type=OEFMessage.Type.REGISTER_SERVICE, id=request_id, service_description=service_description, service_id=service_id) -# msg_bytes = OEFSerializer().encode(register_service_request) -# envelope = Envelope(to=DEFAULT_OEF, sender=cls.public_key_1, protocol_id=OEFMessage.protocol_id, message=msg_bytes) -# cls.mailbox1.send(envelope) -# -# time.sleep(2.0) -# -# # register 'mailbox2' as a service 'barfoo'. -# cls.data_model_barfoo = DataModel("barfoo", attributes=[]) -# service_description = Description({"foo": 1, "bar": "baz"}, data_model=cls.data_model_barfoo) -# register_service_request = OEFMessage(oef_type=OEFMessage.Type.REGISTER_SERVICE, id=request_id, service_description=service_description, service_id=service_id) -# msg_bytes = OEFSerializer().encode(register_service_request) -# envelope = Envelope(to=DEFAULT_OEF, sender=cls.public_key_2, protocol_id=OEFMessage.protocol_id, message=msg_bytes) -# cls.mailbox2.send(envelope) -# -# def test_filtered_search_result(self): -# """Test that the search result contains only the entries matching the query.""" -# request_id = 1 -# query = Query(constraints=[], model=self.data_model_barfoo) -# -# # build and send the request -# search_services_request = OEFMessage(oef_type=OEFMessage.Type.SEARCH_SERVICES, id=request_id, query=query) -# msg_bytes = OEFSerializer().encode(search_services_request) -# envelope = Envelope(to=DEFAULT_OEF, sender=self.public_key_1, protocol_id=OEFMessage.protocol_id, message=msg_bytes) -# self.mailbox1.send(envelope) -# -# # check the result -# response_envelope = self.mailbox1.inbox.get(block=True, timeout=5.0) -# assert response_envelope.protocol_id == OEFMessage.protocol_id -# assert response_envelope.to == self.public_key_1 -# assert response_envelope.sender == DEFAULT_OEF -# search_result = OEFSerializer().decode(response_envelope.message) -# assert search_result.get("type") == OEFMessage.Type.SEARCH_RESULT -# assert search_result.get("agents") == [self.public_key_2] -# -# @classmethod -# def teardown_class(cls): -# """Teardown the test.""" -# cls.mailbox1.disconnect() -# cls.mailbox2.disconnect() +class TestFilteredSearchResult: + """Test that the query system of the search gives the expected result.""" + + @classmethod + def setup_class(cls): + """Set up the test.""" + cls.node = LocalNode() + + cls.public_key_1 = "mailbox1" + cls.public_key_2 = "mailbox2" + cls.mailbox1 = MailBox(OEFLocalConnection(cls.public_key_1, cls.node)) + cls.mailbox2 = MailBox(OEFLocalConnection(cls.public_key_2, cls.node)) + cls.mailbox1.connect() + cls.mailbox2.connect() + + # register 'mailbox2' as a service 'foobar'. + request_id = 1 + service_id = '' + cls.data_model_foobar = DataModel("foobar", attributes=[]) + service_description = Description({"foo": 1, "bar": "baz"}, data_model=cls.data_model_foobar) + register_service_request = OEFMessage(oef_type=OEFMessage.Type.REGISTER_SERVICE, id=request_id, + service_description=service_description, service_id=service_id) + msg_bytes = OEFSerializer().encode(register_service_request) + envelope = Envelope(to=DEFAULT_OEF, sender=cls.public_key_1, protocol_id=OEFMessage.protocol_id, + message=msg_bytes) + cls.mailbox1.send(envelope) + + time.sleep(2.0) + + # register 'mailbox2' as a service 'barfoo'. + cls.data_model_barfoo = DataModel("barfoo", attributes=[]) + service_description = Description({"foo": 1, "bar": "baz"}, data_model=cls.data_model_barfoo) + register_service_request = OEFMessage(oef_type=OEFMessage.Type.REGISTER_SERVICE, id=request_id, + service_description=service_description, service_id=service_id) + msg_bytes = OEFSerializer().encode(register_service_request) + envelope = Envelope(to=DEFAULT_OEF, sender=cls.public_key_2, protocol_id=OEFMessage.protocol_id, + message=msg_bytes) + cls.mailbox2.send(envelope) + + data_model = DataModel("foobar", attributes=[]) + service_description = Description({"foo": 1, "bar": "baz"}, data_model=data_model) + msg = OEFMessage(oef_type=OEFMessage.Type.UNREGISTER_SERVICE, id=0, service_description=service_description, + service_id="Test_service") + msg_bytes = OEFSerializer().encode(msg) + envelope = Envelope(to="mailbox2", sender="mailbox1", protocol_id=OEFMessage.protocol_id, message=msg_bytes) + cls.mailbox1.send(envelope) + + def test_filtered_search_result(self): + """Test that the search result contains only the entries matching the query.""" + request_id = 1 + query = Query(constraints=[], model=self.data_model_barfoo) + + # build and send the request + search_services_request = OEFMessage(oef_type=OEFMessage.Type.SEARCH_SERVICES, id=request_id, query=query) + msg_bytes = OEFSerializer().encode(search_services_request) + envelope = Envelope(to=DEFAULT_OEF, sender=self.public_key_1, protocol_id=OEFMessage.protocol_id, + message=msg_bytes) + self.mailbox1.send(envelope) + + # check the result + response_envelope = self.mailbox1.inbox.get(block=True, timeout=5.0) + assert response_envelope.protocol_id == OEFMessage.protocol_id + assert response_envelope.to == self.public_key_1 + assert response_envelope.sender == DEFAULT_OEF + search_result = OEFSerializer().decode(response_envelope.message) + assert search_result.get("type") == OEFMessage.Type.SEARCH_RESULT + assert search_result.get("agents") == [self.public_key_2] + + def test_filtered_search_agents(self): + """Test that the search result contains only the entries matching the query.""" + request_id = 1 + + query = Query(constraints=[], model=self.data_model_foobar) + # build and send the request + search_agents_request = OEFMessage(oef_type=OEFMessage.Type.SEARCH_AGENTS, id=request_id, query=query) + msg_bytes = OEFSerializer().encode(search_agents_request) + envelope = Envelope(to=DEFAULT_OEF, sender=self.public_key_1, protocol_id=OEFMessage.protocol_id, + message=msg_bytes) + self.mailbox1.send(envelope) + + # check the result + response_envelope = self.mailbox1.inbox.get(block=True, timeout=5.0) + assert response_envelope.protocol_id == OEFMessage.protocol_id + assert response_envelope.sender == DEFAULT_OEF + search_result = OEFSerializer().decode(response_envelope.message) + assert search_result.get("type") == OEFMessage.Type.SEARCH_RESULT + assert search_result.get("agents") == [] + + @classmethod + def teardown_class(cls): + """Teardown the test.""" + cls.mailbox1.disconnect() + cls.mailbox2.disconnect() + + +class TestUnregister: + """Test that the unregister service results to Error Message.""" + + @classmethod + def setup_class(cls): + """Set up the test.""" + cls.node = LocalNode() + + cls.public_key_1 = "mailbox1" + cls.mailbox1 = MailBox(OEFLocalConnection(cls.public_key_1, cls.node)) + + cls.mailbox1.connect() + + def test_unregister_service_result(self): + """Test that at the beginning, the search request returns an empty search result.""" + data_model = DataModel("foobar", attributes=[]) + service_description = Description({"foo": 1, "bar": "baz"}, data_model=data_model) + msg = OEFMessage(oef_type=OEFMessage.Type.UNREGISTER_SERVICE, id=0, service_description=service_description, + service_id="Test_service") + msg_bytes = OEFSerializer().encode(msg) + envelope = Envelope(to=DEFAULT_OEF, sender="mailbox1", protocol_id=OEFMessage.protocol_id, message=msg_bytes) + self.mailbox1.send(envelope) + + # check the result + response_envelope = self.mailbox1.inbox.get(block=True, timeout=5.0) + assert response_envelope.protocol_id == OEFMessage.protocol_id + assert response_envelope.sender == DEFAULT_OEF + result = OEFSerializer().decode(response_envelope.message) + assert result.get("type") == OEFMessage.Type.OEF_ERROR + + @classmethod + def teardown_class(cls): + """Teardown the test.""" + cls.mailbox1.disconnect() + + +class TestAgentMessage: + """Test the the OEF will return Dialogue Error if it doesn't know the public key.""" + + @classmethod + def setup_class(cls): + """Set up the test.""" + cls.node = LocalNode() + + cls.public_key_1 = "mailbox1" + cls.mailbox1 = MailBox(OEFLocalConnection(cls.public_key_1, cls.node)) + + def test_messages(self): + """Test that at the beginning, the search request returns an empty search result.""" + msg = FIPAMessage(0, 0, 0, FIPAMessage.Performative.CFP, query=None) + msg_bytes = FIPASerializer().encode(msg) + envelope = Envelope(to=DEFAULT_OEF, sender="mailbox1", protocol_id=FIPAMessage.protocol_id, message=msg_bytes) + with pytest.raises(ConnectionError): + OEFLocalConnection(self.public_key_1, self.node).send(envelope) + + self.mailbox1.connect() + msg = FIPAMessage(0, 0, 0, FIPAMessage.Performative.CFP, query=None) + msg_bytes = FIPASerializer().encode(msg) + envelope = Envelope(to="mailbox3", sender="mailbox1", protocol_id=FIPAMessage.protocol_id, message=msg_bytes) + self.mailbox1.send(envelope) + + # check the result + response_envelope = self.mailbox1.inbox.get(block=True, timeout=5.0) + assert response_envelope.protocol_id == OEFMessage.protocol_id + assert response_envelope.sender == DEFAULT_OEF + result = OEFSerializer().decode(response_envelope.message) + assert result.get("type") == OEFMessage.Type.DIALOGUE_ERROR + + @classmethod + def teardown_class(cls): + """Teardown the test.""" + cls.mailbox1.disconnect() + + +class TestOEFConnectionFromJson: + """Test the the OEF will return a connection after reading the .json file.""" + + @classmethod + def setup_class(cls): + """Set up the test.""" + cls.node = LocalNode() + cls.public_key_1 = "mailbox1" + + @classmethod + def teardown_class(cls): + """Teardown the test.""" + cls.mailbox1.disconnect() From ba89de3503c36ffb0afaa0baa3a125f00878acd9 Mon Sep 17 00:00:00 2001 From: Aristotelis Date: Fri, 18 Oct 2019 16:56:58 +0100 Subject: [PATCH 10/15] Bug Fix in connection.py handle_agent_message --- aea/connections/local/connection.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aea/connections/local/connection.py b/aea/connections/local/connection.py index 2b59091788..a50cf704ed 100644 --- a/aea/connections/local/connection.py +++ b/aea/connections/local/connection.py @@ -121,7 +121,7 @@ def handle_agent_message(self, envelope: Envelope) -> None: if destination not in self._queues: msg = OEFMessage(oef_type=OEFMessage.Type.DIALOGUE_ERROR, id=STUB_DIALOGUE_ID, dialogue_id=STUB_DIALOGUE_ID, origin=destination) msg_bytes = OEFSerializer().encode(msg) - error_envelope = Envelope(to=destination, sender=envelope.sender, protocol_id=OEFMessage.protocol_id, message=msg_bytes) + error_envelope = Envelope(to=envelope.sender, sender=DEFAULT_OEF, protocol_id=OEFMessage.protocol_id, message=msg_bytes) self._send(error_envelope) return else: From ac21900dd50851b674b1e9abbc8885db38301df0 Mon Sep 17 00:00:00 2001 From: MarcoFavorito Date: Fri, 18 Oct 2019 18:56:39 +0200 Subject: [PATCH 11/15] make tests pass with Python 3.6 --- aea/registries/base.py | 3 ++- aea/skills/base.py | 3 ++- tests/conftest.py | 3 +++ tests/test_cli/test_commands/test_gui.py | 2 +- tests/test_cli/test_commands/test_run.py | 6 +++++- tox.ini | 2 +- 6 files changed, 14 insertions(+), 5 deletions(-) diff --git a/aea/registries/base.py b/aea/registries/base.py index c3da730473..53caf8ec07 100644 --- a/aea/registries/base.py +++ b/aea/registries/base.py @@ -146,7 +146,8 @@ def populate(self, directory: str) -> None: logger.warning("No protocol found.") return - protocols_packages = list(filter(lambda x: PACKAGE_NAME_REGEX.match(x), protocols_spec.loader.contents())) # type: ignore + loader_contents = [path.name for path in Path(directory, "protocols").iterdir()] + protocols_packages = list(filter(lambda x: PACKAGE_NAME_REGEX.match(x), loader_contents)) # type: ignore logger.debug("Processing the following protocol package: {}".format(protocols_packages)) for protocol_name in protocols_packages: try: diff --git a/aea/skills/base.py b/aea/skills/base.py index 933ac9dba2..e2f6427dc5 100644 --- a/aea/skills/base.py +++ b/aea/skills/base.py @@ -493,7 +493,8 @@ def from_dir(cls, directory: str, agent_context: AgentContext) -> Optional['Skil skill_module = importlib.util.module_from_spec(skills_spec) sys.modules[skill_config.name + "_skill"] = skill_module - skills_packages = list(filter(lambda x: not x.startswith("__"), skills_spec.loader.contents())) # type: ignore + loader_contents = [path.name for path in Path(directory).iterdir()] + skills_packages = list(filter(lambda x: not x.startswith("__"), loader_contents)) # type: ignore logger.debug("Processing the following skill package: {}".format(skills_packages)) skill_context = SkillContext(agent_context) diff --git a/tests/conftest.py b/tests/conftest.py index a461a2826a..ce2b4193db 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -23,6 +23,7 @@ import logging import os import socket +import sys import time from threading import Timer from typing import Optional @@ -224,6 +225,8 @@ def _create_oef_docker_image(oef_addr_, oef_port_) -> Container: @pytest.fixture(scope="session") def network_node(oef_addr, oef_port, pytestconfig): """Network node initialization.""" + if sys.version_info < (3, 7): + pytest.skip("Python version < 3.7 not supported by the OEF.") if pytestconfig.getoption("no_integration_tests"): pytest.skip('skipped: no OEF running') return diff --git a/tests/test_cli/test_commands/test_gui.py b/tests/test_cli/test_commands/test_gui.py index 9507302ab8..8c22a7d732 100644 --- a/tests/test_cli/test_commands/test_gui.py +++ b/tests/test_cli/test_commands/test_gui.py @@ -47,7 +47,7 @@ def setup_class(cls): cls.t = tempfile.mkdtemp() os.chdir(cls.t) cls.proc = subprocess.Popen(["aea", *CLI_LOG_OPTION, "gui"]) - time.sleep(3.0) + time.sleep(5.0) def test_gui(self, pytestconfig): """Test that the gui process has been spawned correctly.""" diff --git a/tests/test_cli/test_commands/test_run.py b/tests/test_cli/test_commands/test_run.py index 0c3f413999..68ae740c30 100644 --- a/tests/test_cli/test_commands/test_run.py +++ b/tests/test_cli/test_commands/test_run.py @@ -199,6 +199,10 @@ def setup_class(cls): assert result.exit_code == 0 os.chdir(Path(cls.t, cls.agent_name)) + + result = cls.runner.invoke(cli, [*CLI_LOG_OPTION, "add", "connection", "local"]) + assert result.exit_code == 0 + shutil.copytree(Path(CUR_PATH, "data", "exception_skill"), Path(cls.t, cls.agent_name, "skills", "exception")) config_path = Path(cls.t, cls.agent_name, DEFAULT_AEA_CONFIG_FILE) config = yaml.safe_load(open(config_path)) @@ -206,7 +210,7 @@ def setup_class(cls): yaml.safe_dump(config, open(config_path, "w")) try: - cli.main([*CLI_LOG_OPTION, "run"]) + cli.main([*CLI_LOG_OPTION, "run", "--connection", "local"]) except SystemExit as e: cls.exit_code = e.code diff --git a/tox.ini b/tox.ini index 8673016b87..525421ec9e 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] # envlist = flake8, mypy, py37, py36, docs -envlist = flake8, mypy, py37, docs +envlist = flake8, mypy, py37, py36, docs skipsdist = True ignore_basepython_conflict = True From c2ee3f04a4dc104accf1b0d0ac72bf317d35512d Mon Sep 17 00:00:00 2001 From: MarcoFavorito Date: Fri, 18 Oct 2019 19:04:22 +0200 Subject: [PATCH 12/15] update Jenkinsfile to include py36 tests. --- Jenkinsfile | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index a730d19161..925bcdf581 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -37,13 +37,13 @@ pipeline { } // docs -// stage('Unit Tests: Python 3.6') { -// -// steps { -// sh 'tox -e py36 -- --no-integration-tests' -// } -// -// } // unit tests: python 3.6 + stage('Unit Tests: Python 3.6') { + + steps { + sh 'tox -e py36 -- --no-integration-tests --ci' + } + + } // unit tests: python 3.6 stage('Unit Tests: Python 3.7') { From ca03317b2aee30113502da68d61c0ac80f04bd2c Mon Sep 17 00:00:00 2001 From: David Minarsch Date: Fri, 18 Oct 2019 23:13:51 +0200 Subject: [PATCH 13/15] Fixes failing tests --- tests/test_crypto/test_crypto.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/test_crypto/test_crypto.py b/tests/test_crypto/test_crypto.py index c4a04b7ab3..1685c7d957 100644 --- a/tests/test_crypto/test_crypto.py +++ b/tests/test_crypto/test_crypto.py @@ -18,20 +18,19 @@ # ------------------------------------------------------------------------------ """This module contains the tests of the crypto module.""" +import os from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat from aea.crypto.base import DefaultCrypto, _load_pem_private_key_from_path from ..conftest import ROOT_DIR -from pathlib import Path -PRIVATE_KEY_PEM_PATH = ROOT_DIR + "/tests/data/priv.pem" +PRIVATE_KEY_PEM_PATH = os.path.join(ROOT_DIR, "tests/data/priv.pem") def test_initialization_from_existing_private_key(): """Test that the initialization from an existing private key works correctly.""" - path = Path(PRIVATE_KEY_PEM_PATH) - private_key = _load_pem_private_key_from_path(path=path) + private_key = _load_pem_private_key_from_path(path=PRIVATE_KEY_PEM_PATH) assert private_key is not None, "The private key is not None after the loading!" c = DefaultCrypto(private_key_pem_path=PRIVATE_KEY_PEM_PATH) From 5b55eacf2b3b54edda7e09c40302527124fc8251 Mon Sep 17 00:00:00 2001 From: David Minarsch Date: Fri, 18 Oct 2019 23:44:13 +0200 Subject: [PATCH 14/15] Prepare develop for version 0.1.9 --- HISTORY.rst | 7 +++++++ README.md | 4 ---- aea/__version__.py | 2 +- deploy-image/README.md | 3 +-- deploy-image/docker-env.sh | 2 +- develop-image/docker-env.sh | 2 +- 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index bf8c31ef21..f34354f8da 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -69,3 +69,10 @@ Release History - Adds full test coverage on cli - Improves docs - Multiple additional minor fixes and changes + +0.1.9 (2019-10-18) +------------------- + +- Stability improvements +- Higher test coverage, including on Python 3.6 +- Multiple additional minor fixes and changes diff --git a/README.md b/README.md index a1b56153b1..f66852947d 100644 --- a/README.md +++ b/README.md @@ -50,10 +50,6 @@ The following dependency is only relevant if you intend to contribute to the rep The following steps are only relevant if you intend to contribute to the repository. They are not required for agent development. -- Clear cache - - pipenv --clear - - Install development dependencies: pipenv install --dev diff --git a/aea/__version__.py b/aea/__version__.py index 6d4c90140f..0d65f86f57 100644 --- a/aea/__version__.py +++ b/aea/__version__.py @@ -23,7 +23,7 @@ __title__ = 'aea' __description__ = 'Autonomous Economic Agent framework' __url__ = 'https://github.com/fetchai/agents-aea.git' -__version__ = '0.1.8' +__version__ = '0.1.9' __author__ = 'Fetch.AI Limited' __license__ = 'Apache 2.0' __copyright__ = '2019 Fetch.AI Limited' diff --git a/deploy-image/README.md b/deploy-image/README.md index f0fdd671a8..c582d1ba1b 100644 --- a/deploy-image/README.md +++ b/deploy-image/README.md @@ -6,8 +6,7 @@ All the commands must be executed from the parent directory, if not stated other We recommend using the following command for building: - ./deploy-image/scripts/docker-build-img.sh \ - -t aea-deploy:latest -- + ./deploy-image/scripts/docker-build-img.sh -t aea-deploy:latest -- ## Run diff --git a/deploy-image/docker-env.sh b/deploy-image/docker-env.sh index dc61a6ee56..95bf4ed780 100755 --- a/deploy-image/docker-env.sh +++ b/deploy-image/docker-env.sh @@ -1,7 +1,7 @@ #!/bin/bash # Swap the following lines if you want to work with 'latest' -DOCKER_IMAGE_TAG=aea-deploy:0.1.8 +DOCKER_IMAGE_TAG=aea-deploy:0.1.9 # DOCKER_IMAGE_TAG=aea-deploy:latest DOCKER_BUILD_CONTEXT_DIR=.. diff --git a/develop-image/docker-env.sh b/develop-image/docker-env.sh index e9d1c10396..af077bb35c 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=aea-develop:0.1.8 +DOCKER_IMAGE_TAG=aea-develop:0.1.9 # DOCKER_IMAGE_TAG=aea-develop:latest DOCKER_BUILD_CONTEXT_DIR=.. From 32ed6a80ba1fe202d62cd1d56f6e5830361725ac Mon Sep 17 00:00:00 2001 From: David Minarsch Date: Fri, 18 Oct 2019 23:48:51 +0200 Subject: [PATCH 15/15] Updates docs --- docs/skill-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/skill-guide.md b/docs/skill-guide.md index 610d9ea4dc..2f96d3f941 100644 --- a/docs/skill-guide.md +++ b/docs/skill-guide.md @@ -13,7 +13,7 @@ aea create my_agent && cd my_agent aea scaffold skill my_search ``` -In the following steps, we will replace each one of the scaffolded `Behaviour`, `Handler` and `Task` in `my_agent/skills/my_search` with our implementation. +In the following steps, we will replace each one of the scaffolded `Behaviour`, `Handler` and `Task` in `my_agent/skills/my_search` with our implementation. We will build a simple skill which lets the agent send a search query to the [OEF](https://docs.fetch.ai/oef/) and process the resulting response. ## Step 2: Develop a Behaviour