Skip to content

Commit

Permalink
Merge pull request #1753 from fetchai/develop
Browse files Browse the repository at this point in the history
Release 0.6.1
  • Loading branch information
DavidMinarsch authored Sep 17, 2020
2 parents ec99bc7 + b6b237a commit ce418be
Show file tree
Hide file tree
Showing 272 changed files with 8,727 additions and 2,447 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ jobs:
pip install tox
sudo apt-get install -y protobuf-compiler
- name: Run all tests
run: tox -e py3.7-cov -- --ignore=tests/test_docs --ignore=tests/test_examples --ignore=tests/test_packages/test_contracts --ignore=tests/test_packages/test_protocols --ignore=tests/test_packages/test_skills -m 'not unstable'
run: tox -e py3.7-cov -- --ignore=tests/test_docs --ignore=tests/test_examples --ignore=tests/test_packages/test_contracts --ignore=tests/test_packages/test_skills -m 'not unstable'
continue-on-error: true
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v1
Expand Down
18 changes: 18 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
# Release History

## 0.6.1 (2020-09-17)

- Adds a standalone script to deploy an ACN node
- Adds filtering of out-dated addresses in DHT lookups
- Updates multiple developer scripts
- Increases code coverage of all protocols to 100%
- Fixes a disconnection issue of the multiplexer
- Extends soef connection to support additional registration commands and search responses
- Extends oef_search protocol to include success performative and agent info in search response
- Adds README.mds to all skills
- Adds configurable exception policy handling for multiplexer
- Fixes support for http headers in http server connection
- Adds additional consistency checks on addresses in dialogues
- Exposes decision maker address on skill context
- Adds comprehensive benchmark scripts
- Multiple docs updates including additional explanations of soef usage
- Multiple additional tests and test stability fixes

## 0.6.0 (2020-09-01)

- Makes FetchAICrypto default again
Expand Down
2 changes: 1 addition & 1 deletion aea/__version__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
__title__ = "aea"
__description__ = "Autonomous Economic Agent framework"
__url__ = "https://github.com/fetchai/agents-aea.git"
__version__ = "0.6.0"
__version__ = "0.6.1"
__author__ = "Fetch.AI Limited"
__license__ = "Apache-2.0"
__copyright__ = "2019 Fetch.AI Limited"
9 changes: 7 additions & 2 deletions aea/aea.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ def __init__(
DecisionMakerHandler
] = DefaultDecisionMakerHandler,
skill_exception_policy: ExceptionPolicyEnum = ExceptionPolicyEnum.propagate,
connection_exception_policy: ExceptionPolicyEnum = ExceptionPolicyEnum.propagate,
loop_mode: Optional[str] = None,
runtime_mode: Optional[str] = None,
default_connection: Optional[PublicId] = None,
Expand Down Expand Up @@ -111,6 +112,10 @@ def __init__(
:return: None
"""

self._skills_exception_policy = skill_exception_policy
self._connection_exception_policy = connection_exception_policy

super().__init__(
identity=identity,
connections=[],
Expand All @@ -119,6 +124,7 @@ def __init__(
loop_mode=loop_mode,
runtime_mode=runtime_mode,
)

aea_logger = AgentLoggerAdapter(
logger=logging.getLogger(__name__), agent_name=identity.name
)
Expand All @@ -140,6 +146,7 @@ def __init__(
default_connection,
default_routing if default_routing is not None else {},
search_service_address,
decision_maker_handler.self_address,
**kwargs,
)
self._execution_timeout = execution_timeout
Expand All @@ -149,8 +156,6 @@ def __init__(
self.resources, self.runtime.decision_maker.message_out_queue
)

self._skills_exception_policy = skill_exception_policy

self._setup_loggers()

@property
Expand Down
32 changes: 32 additions & 0 deletions aea/aea_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ class AEABuilder:
DecisionMakerHandler
] = DefaultDecisionMakerHandler
DEFAULT_SKILL_EXCEPTION_POLICY = ExceptionPolicyEnum.propagate
DEFAULT_CONNECTION_EXCEPTION_POLICY = ExceptionPolicyEnum.propagate
DEFAULT_LOOP_MODE = "async"
DEFAULT_RUNTIME_MODE = "threaded"
DEFAULT_SEARCH_SERVICE_ADDRESS = "fetchai/soef:*"
Expand Down Expand Up @@ -350,6 +351,7 @@ def _reset(self, is_full_reset: bool = False) -> None:
self._max_reactions: Optional[int] = None
self._decision_maker_handler_class: Optional[Type[DecisionMakerHandler]] = None
self._skill_exception_policy: Optional[ExceptionPolicyEnum] = None
self._connection_exception_policy: Optional[ExceptionPolicyEnum] = None
self._default_routing: Dict[PublicId, PublicId] = {}
self._loop_mode: Optional[str] = None
self._runtime_mode: Optional[str] = None
Expand Down Expand Up @@ -440,6 +442,19 @@ def set_skill_exception_policy(
self._skill_exception_policy = skill_exception_policy
return self

def set_connection_exception_policy(
self, connection_exception_policy: Optional[ExceptionPolicyEnum]
) -> "AEABuilder": # pragma: nocover
"""
Set skill exception policy.
:param skill_exception_policy: the policy
:return: self
"""
self._connection_exception_policy = connection_exception_policy
return self

def set_default_routing(
self, default_routing: Dict[PublicId, PublicId]
) -> "AEABuilder":
Expand Down Expand Up @@ -877,6 +892,7 @@ def build(self, connection_ids: Optional[Collection[PublicId]] = None,) -> AEA:
max_reactions=self._get_max_reactions(),
decision_maker_handler_class=self._get_decision_maker_handler_class(),
skill_exception_policy=self._get_skill_exception_policy(),
connection_exception_policy=self._get_connection_exception_policy(),
default_routing=self._get_default_routing(),
default_connection=self._get_default_connection(),
loop_mode=self._get_loop_mode(),
Expand Down Expand Up @@ -947,6 +963,18 @@ def _get_skill_exception_policy(self) -> ExceptionPolicyEnum:
else self.DEFAULT_SKILL_EXCEPTION_POLICY
)

def _get_connection_exception_policy(self) -> ExceptionPolicyEnum:
"""
Return the skill exception policy.
:return: the skill exception policy.
"""
return (
self._connection_exception_policy
if self._connection_exception_policy is not None
else self.DEFAULT_CONNECTION_EXCEPTION_POLICY
)

def _get_default_routing(self) -> Dict[PublicId, PublicId]:
"""
Return the default routing.
Expand Down Expand Up @@ -1139,6 +1167,10 @@ def set_from_configuration(
self.set_skill_exception_policy(
ExceptionPolicyEnum(agent_configuration.skill_exception_policy)
)
if agent_configuration.connection_exception_policy is not None:
self.set_connection_exception_policy(
ExceptionPolicyEnum(agent_configuration.connection_exception_policy)
)
self.set_default_routing(agent_configuration.default_routing)
self.set_loop_mode(agent_configuration.loop_mode)
self.set_runtime_mode(agent_configuration.runtime_mode)
Expand Down
2 changes: 1 addition & 1 deletion aea/cli/registry/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"""Settings for operating Registry with CLI."""


REGISTRY_API_URL = "https://agents-registry.prod.fetch-ai.com"
REGISTRY_API_URL = "https://agents-registry.prod.fetch-ai.com/api/v1"
# we ignore issue B105 because this is not an hard-coded authentication token,
# but the name of the field in the configuration file.
AUTH_TOKEN_KEY = "auth_token" # nosec
63 changes: 45 additions & 18 deletions aea/cli/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

import os
from pathlib import Path
from typing import Dict, List, cast
from typing import Dict, List, Tuple, cast

import click

Expand Down Expand Up @@ -62,47 +62,52 @@ def search(click_context, local):

@search.command()
@click.option("--query", default="", help="Query string to search Connections by name.")
@click.option("--page", type=int, default=1, help="Page number to display.")
@pass_ctx
def connections(ctx: Context, query):
def connections(ctx: Context, query, page):
"""Search for Connections."""
item_type = "connection"
_output_search_results(item_type, search_items(ctx, item_type, query))
_output_search_results(item_type, *search_items(ctx, item_type, query, page), page)


@search.command()
@click.option("--query", default="", help="Query string to search Contracts by name.")
@click.option("--page", type=int, default=1, help="Page number to display.")
@pass_ctx
def contracts(ctx: Context, query):
def contracts(ctx: Context, query, page):
"""Search for Contracts."""
item_type = "contract"
_output_search_results(item_type, search_items(ctx, item_type, query))
_output_search_results(item_type, *search_items(ctx, item_type, query, page), page)


@search.command()
@click.option("--query", default="", help="Query string to search Protocols by name.")
@click.option("--page", type=int, default=1, help="Page number to display.")
@pass_ctx
def protocols(ctx: Context, query):
def protocols(ctx: Context, query, page):
"""Search for Protocols."""
item_type = "protocol"
_output_search_results(item_type, search_items(ctx, item_type, query))
_output_search_results(item_type, *search_items(ctx, item_type, query, page), page)


@search.command()
@click.option("--query", default="", help="Query string to search Skills by name.")
@click.option("--page", type=int, default=1, help="Page number to display.")
@pass_ctx
def skills(ctx: Context, query):
def skills(ctx: Context, query, page):
"""Search for Skills."""
item_type = "skill"
_output_search_results(item_type, search_items(ctx, item_type, query))
_output_search_results(item_type, *search_items(ctx, item_type, query, page), page)


@search.command()
@click.option("--query", default="", help="Query string to search Agents by name.")
@click.option("--page", type=int, default=1, help="Page number to display.")
@pass_ctx
def agents(ctx: Context, query):
def agents(ctx: Context, query, page):
"""Search for Agents."""
item_type = "agent"
_output_search_results(item_type, search_items(ctx, item_type, query))
_output_search_results(item_type, *search_items(ctx, item_type, query, page), page)


def setup_search_ctx(ctx: Context, local: bool) -> None:
Expand Down Expand Up @@ -198,33 +203,55 @@ def _search_items_locally(ctx, item_type_plural):
return sorted(result, key=lambda k: k["name"])


def search_items(ctx: Context, item_type: str, query: str) -> List:
def search_items(
ctx: Context, item_type: str, query: str, page: int
) -> Tuple[List, int]:
"""
Search items by query and click.echo results.
:param ctx: Context object.
:param item_type: item type.
:param query: query string.
:return: None
:return: (List of items, int items total count).
"""
click.echo('Searching for "{}"...'.format(query))
item_type_plural = item_type + "s"
if ctx.config.get("is_local"):
return _search_items_locally(ctx, item_type_plural)
return request_api("GET", "/{}".format(item_type_plural), params={"search": query})
results = _search_items_locally(ctx, item_type_plural)
count = len(results)
else:
resp = request_api(
"GET",
"/{}".format(item_type_plural),
params={"search": query, "page": page},
)
results = resp["results"]
count = resp["count"]
return results, count


def _output_search_results(item_type: str, results: List[Dict]) -> None:
def _output_search_results(
item_type: str, results: List[Dict], count: int, page: int
) -> None:
"""
Output search results.
:param results: list of found items
:param item_type: str item type.
:param results: list of found items.
:param count: items total count.
"""
item_type_plural = item_type + "s"
if len(results) == 0:
len_results = len(results)
if len_results == 0:
click.echo("No {} found.".format(item_type_plural)) # pragma: no cover
else:
click.echo("{} found:\n".format(item_type_plural.title()))
click.echo(format_items(results))
if count > len_results:
click.echo(
"{} {} out of {}.\nPage {}".format(
len_results, item_type_plural, count, page
)
) # pragma: no cover
4 changes: 2 additions & 2 deletions aea/cli_gui/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ def get_registered_items(item_type: str):
ctx = Context(cwd=app_context.agents_dir)
try:
cli_setup_search_ctx(ctx, local=app_context.local)
result = cli_search_items(ctx, item_type, query="")
result, _ = cli_search_items(ctx, item_type, query="", page=1)
except ClickException:
return {"detail": "Failed to search items."}, 400 # 400 Bad request
else:
Expand All @@ -135,7 +135,7 @@ def search_registered_items(item_type: str, search_term: str):
ctx = Context(cwd=app_context.agents_dir)
try:
cli_setup_search_ctx(ctx, local=app_context.local)
result = cli_search_items(ctx, item_type, query=search_term)
result, _ = cli_search_items(ctx, item_type, query=search_term, page=1)
except ClickException:
return {"detail": "Failed to search items."}, 400 # 400 Bad request
else:
Expand Down
8 changes: 8 additions & 0 deletions aea/configurations/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1296,6 +1296,7 @@ def __init__(
max_reactions: Optional[int] = None,
decision_maker_handler: Optional[Dict] = None,
skill_exception_policy: Optional[str] = None,
connection_exception_policy: Optional[str] = None,
default_routing: Optional[Dict] = None,
loop_mode: Optional[str] = None,
runtime_mode: Optional[str] = None,
Expand Down Expand Up @@ -1332,7 +1333,9 @@ def __init__(
self.period: Optional[float] = period
self.execution_timeout: Optional[float] = execution_timeout
self.max_reactions: Optional[int] = max_reactions

self.skill_exception_policy: Optional[str] = skill_exception_policy
self.connection_exception_policy: Optional[str] = connection_exception_policy

self.decision_maker_handler = (
decision_maker_handler if decision_maker_handler is not None else {}
Expand Down Expand Up @@ -1504,6 +1507,8 @@ def json(self) -> Dict:
config["decision_maker_handler"] = self.decision_maker_handler
if self.skill_exception_policy is not None:
config["skill_exception_policy"] = self.skill_exception_policy
if self.connection_exception_policy is not None:
config["connection_exception_policy"] = self.skill_exception_policy
if self.default_routing != {}:
config["default_routing"] = {
str(key): str(value) for key, value in self.default_routing.items()
Expand Down Expand Up @@ -1537,6 +1542,9 @@ def from_json(cls, obj: Dict):
max_reactions=cast(int, obj.get("max_reactions")),
decision_maker_handler=cast(Dict, obj.get("decision_maker_handler", {})),
skill_exception_policy=cast(str, obj.get("skill_exception_policy")),
connection_exception_policy=cast(
str, obj.get("connection_exception_policy")
),
default_routing=cast(Dict, obj.get("default_routing", {})),
loop_mode=cast(str, obj.get("loop_mode")),
runtime_mode=cast(str, obj.get("runtime_mode")),
Expand Down
3 changes: 3 additions & 0 deletions aea/configurations/schemas/aea-config_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@
"skill_exception_policy": {
"$ref": "definitions.json#/definitions/skill_exception_policy"
},
"connection_exception_policy": {
"$ref": "definitions.json#/definitions/connection_exception_policy"
},
"default_routing": {
"type": "object",
"uniqueItems": true,
Expand Down
4 changes: 4 additions & 0 deletions aea/configurations/schemas/definitions.json
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@
"type": "string",
"enum": ["propagate", "just_log", "stop_and_exit"]
},
"connection_exception_policy": {
"type": "string",
"enum": ["propagate", "just_log", "stop_and_exit"]
},
"loop_mode": {
"type": "string",
"enum": ["async", "sync"]
Expand Down
Loading

0 comments on commit ce418be

Please sign in to comment.