Skip to content

Commit

Permalink
GET abilities by fact names endpoint working'
Browse files Browse the repository at this point in the history
  • Loading branch information
mkouremetis committed Apr 17, 2023
1 parent 3438ffc commit 453a35d
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 22 deletions.
4 changes: 2 additions & 2 deletions app/api/v2/handlers/ability_api.py
Expand Up @@ -4,7 +4,7 @@
from app.api.v2.handlers.base_object_api import BaseObjectApi
from app.api.v2.managers.ability_api_manager import AbilityApiManager
from app.api.v2.schemas.base_schemas import BaseGetAllQuerySchema, BaseGetOneQuerySchema
from app.objects.c_ability import Ability, AbilitySchema, GetAbilityByFactSchema
from app.objects.c_ability import Ability, AbilitySchema, GetAbilityByFactSchema, GetAbilityByFactResponseSchema


class AbilityApi(BaseObjectApi):
Expand Down Expand Up @@ -51,7 +51,7 @@ async def get_ability_by_id(self, request: web.Request):
@aiohttp_apispec.docs(tags=['abilities'], summary='Get abilities by required/produced facts.',
description='Searches for abilities that require or produce the supplied fact names.')
@aiohttp_apispec.querystring_schema(GetAbilityByFactSchema)
@aiohttp_apispec.response_schema(AbilitySchema(many=True, partial=True),
@aiohttp_apispec.response_schema(GetAbilityByFactResponseSchema,
description='Returns a list of abilities.')
async def get_abilities_by_facts(self, request: web.Request):
fact_names = await request.json()
Expand Down
4 changes: 2 additions & 2 deletions app/api/v2/managers/ability_api_manager.py
Expand Up @@ -51,8 +51,8 @@ async def update_on_disk_object(self, obj: Any, data: dict, ram_key: str, id_pro
await self._save_and_reload_object(file_path, existing_obj_data, obj_class, obj.access)
return next(self.find_objects(ram_key, {id_property: obj_id}))

async def get_abilities_by_facts(self, required: list[str] = None, produced: list[str] = None):
return await self._planning_svc.get_abilities_by_facts(required_facts=required, produced_facts=produced)
async def get_abilities_by_facts(self, requires: list[str] = None, produces: list[str] = None):
return await self._planning_svc.get_abilities_by_facts(required_facts=requires, produced_facts=produces, dump=True)

def _validate_ability_data(self, create: bool, data: dict):
# Correct ability_id key for ability file saving.
Expand Down
18 changes: 12 additions & 6 deletions app/objects/c_ability.py
Expand Up @@ -11,12 +11,6 @@
from app.utility.base_world import AccessSchema


class GetAbilityByFactSchema(ma.Schema):

required = ma.fields.List(ma.fields.String(), required=False)
produced = ma.fields.List(ma.fields.String(), required=False)


class AbilitySchema(ma.Schema):

ability_id = ma.fields.String()
Expand Down Expand Up @@ -49,6 +43,18 @@ def build_ability(self, data, **kwargs):
return None if kwargs.get('partial') is True else Ability(**data)


class GetAbilityByFactSchema(ma.Schema):

requires = ma.fields.List(ma.fields.String(), required=False)
produces = ma.fields.List(ma.fields.String(), required=False)


class GetAbilityByFactResponseSchema(ma.Schema):

requires = ma.fields.Dict(keys=ma.fields.String(), values=ma.fields.List(ma.fields.Nested(AbilitySchema)))
produces = ma.fields.Dict(ma.fields.Dict)


class Ability(FirstClassObjectInterface, BaseObject):

schema = AbilitySchema()
Expand Down
26 changes: 14 additions & 12 deletions app/service/planning_svc.py
Expand Up @@ -323,13 +323,14 @@ async def adversary_fact_requirements(self, adversary):

return missing_fact_reqs

async def get_abilities_by_facts(self, required_facts: list[str] = None, produced_facts: list[str] = None) -> list[tuple]:
async def get_abilities_by_facts(self, required_facts: list[str] = None, produced_facts: list[str] = None, dump: bool = False) -> list[tuple]:
"""
Args:
required_facts: required fact names (NOTE: Not Fact objects but names, i.e. Fact.name)
produced_facts: produced fact names (NOTE: Not Fact objects but names, i.e. Fact.name)
required_facts (list): required fact names (NOTE: Not Fact objects but names, i.e. Fact.name)
produced_facts (list): produced fact names (NOTE: Not Fact objects but names, i.e. Fact.name)
dump (bool): return Abilites as dict/json, not Ability objects
"""
abilities = dict(required={}, produced={})
abilities = dict(requires={}, produces={})
if required_facts is None:
required_facts = []
if produced_facts is None:
Expand All @@ -342,22 +343,23 @@ async def get_abilities_by_facts(self, required_facts: list[str] = None, produce
for _platform, name_executor in executors.items():
for _name, executor in name_executor.items():
# required facts
if getattr(executor.test, False):
if getattr(executor, 'test', False):
for fact_ in re.findall(BasePlanningService.re_variable, executor.test):
if fact_ in required_facts:
if fact_ not in abilities['required']:
abilities['required'][fact_] = set([])
abilities['required'][fact_].add(ability_)

if fact_ not in abilities['requires']:
abilities['requires'][fact_] = []
a = ability_.diplay if dump else ability_
abilities['requires'][fact_].append(a)
# produced facts
for parser in executor.parsers:
for parserconfig in parser.parserconfigs:
for fact_type in ['source', 'target', 'edge']:
fact_ = getattr(parserconfig, fact_type, False)
if fact_ in produced_facts:
if fact_ not in abilities['produced']:
abilities['produced'][fact_] = set([])
abilities['produced'][fact_].add(ability_)
if fact_ not in abilities['produces']:
abilities['produces'][fact_] = []
a = ability_.diplay if dump else ability_
abilities['produces'][fact_].append(a)
return abilities

@staticmethod
Expand Down

0 comments on commit 453a35d

Please sign in to comment.