Skip to content

Commit

Permalink
Merge branch 'devel' into rtfd
Browse files Browse the repository at this point in the history
  • Loading branch information
s-kostyuk committed Sep 11, 2017
2 parents 09ef017 + e3aba27 commit 018a21c
Show file tree
Hide file tree
Showing 10 changed files with 242 additions and 21 deletions.
21 changes: 19 additions & 2 deletions dpl/api/api_gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,23 @@ def _thing_to_dict(self, thing: Thing) -> dict:

return thing_dict

def _thing_to_dict_legacy(self, thing: Thing) -> dict:
"""
Convert a thing object to a corresponding dict representation that is compatible
to the legacy API
:param thing: an instance of Thing to be converted
:return: a corresponding dict
"""
warnings.warn("Legacy representation of things will be dropped in the next release"
"of this platform. Please, switch to the '_thing_to_dict' method usage",
PendingDeprecationWarning)

thing_dict = self._thing_to_dict(thing)
thing_dict['description'] = thing_dict['friendly_name']

return thing_dict

def get_things(self, token: str) -> List[Dict]:
"""
Receive a full list of data about things
Expand All @@ -77,7 +94,7 @@ def get_things(self, token: str) -> List[Dict]:
things = self._pm.fetch_all_things()

for thing in things:
result.append(self._thing_to_dict(thing))
result.append(self._thing_to_dict_legacy(thing))

return result

Expand Down Expand Up @@ -112,7 +129,7 @@ def get_thing(self, token: str, thing_id: str) -> Dict:

thing = self._get_thing(token, thing_id)

return self._thing_to_dict(thing)
return self._thing_to_dict_legacy(thing)

# FIXME: CC2: Make this method a coroutine?
# FIXME: Specify a return value type
Expand Down
29 changes: 27 additions & 2 deletions dpl/api/rest_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

# Include DPL modules
from dpl.api import ApiGateway
from dpl.utils import JsonEnumEncoder
from dpl.utils import JsonEnumEncoder, filtering
from . import exceptions


Expand Down Expand Up @@ -247,6 +247,28 @@ async def auth_options_handler(self, request: web.Request) -> web.Response:
headers={'Allow': 'POST, HEAD, OPTIONS'}
)

@staticmethod
def _params_to_thing_filter_pattern(request: web.Request) -> dict:
"""
Fetch field names and their values from HTTP request query parameters
and save them to new dictionary object that can be used for filtering of things.
:param request: request to be processed
:return: a dict, filter pattern
"""
# Specified a set of fields that are allowed for filtering
# (like here: https://goo.gl/KUBHTZ)
filter_fields = ('placement', 'type')

result = dict()
query_params = request.query

for field_name in filter_fields:
if field_name in query_params:
result[field_name] = query_params[field_name]

return result

@restricted_access_decorator
async def things_get_handler(self, request: web.Request, token: str = None) -> web.Response:
"""
Expand All @@ -258,8 +280,11 @@ async def things_get_handler(self, request: web.Request, token: str = None) -> w
"""
try:
things = self._gateway.get_things(token)
pattern = self._params_to_thing_filter_pattern(request)

filtered = filtering.filter_items(things, pattern)

return make_json_response({"things": things})
return make_json_response({"things": filtered})
except PermissionError as e:
return make_error_response(status=400, message=str(e))

Expand Down
4 changes: 2 additions & 2 deletions dpl/platforms/platform_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def init_things(self, config: List[Dict]) -> None:
thing_id = item["id"]
thing_platform = item["platform"]
thing_type = item["type"]
thing_description = item["description"]
thing_friendly_name = item.get("friendly_name", None)
thing_placement = item["placement"]
con_id = item["con_id"]
con_params = item["con_params"]
Expand Down Expand Up @@ -119,7 +119,7 @@ def init_things(self, config: List[Dict]) -> None:
con_instance=connection,
con_params=con_params,
metadata={
"description": thing_description,
"friendly_name": thing_friendly_name,
"type": thing_type,
"id": thing_id,
"placement": thing_placement
Expand Down
67 changes: 67 additions & 0 deletions dpl/utils/filtering.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
from typing import List, Dict


def is_correct_filter(filter_fields, filter_pattern: dict = None):
"""
Checks if all keys of filter_pattern are present in a set of filter_fields
:param filter_fields: a set of fields names for which filtering is allowed
:param filter_pattern: a dictionary used for filtering with keys = field names
and values = desired values of fields itself
:return: True if all keys of filter_pattern are present in a set of filter_fields,
False otherwise.
"""
for item in filter_pattern.keys():
if item not in filter_fields:
return False

return True


def is_matches(obj: dict, filter_pattern: dict) -> bool:
"""
Checks if all values of fields in the filter_pattern are the
same as the corresponding values in 'obj' dictionary
For example:
>>> pattern = {"placement": "R1"}
>>> obj = {"id": 1, "placement": "R1"}
>>> is_matches(obj, pattern)
True
>>> is_matches(obj, {})
True
>>> new_pattern = {"nonexistent": "value"}
>>> is_matches(obj, new_pattern)
False
:param obj: a dictionary representation of some object
:param filter_pattern: a pattern for filtering
:return: True if all keys (field names) from filter_pattern
are also present in obj dictionary AND those keys
have the same values. Returns False otherwise.
"""
for key, value in filter_pattern.items():
if obj.get(key, None) != value:
return False

return True


def filter_items(items: List[Dict], filter_pattern: dict) -> List[Dict]:
"""
Performs a simple filtering of data. Returns a subset of items which have
their values equal to the corresponding values in filter_pattern.
For example:
>>> test_values = [{"id": 1, "placement": "R1"}, {"id": 2, "placement": "R2"}]
>>> filter_pattern = {"placement": "R1"}
>>> filter_items(test_values, filter_pattern)
[{'placement': 'R1', 'id': 1}]
:param items: a list of dict-like representations of some objects
:param filter_pattern: a dictionary of field names and their desired values
:return: a list of thing representations which have values corresponding to filtering params
"""
result = [i for i in items if is_matches(i, filter_pattern)]

return result
6 changes: 3 additions & 3 deletions samples/config/things/doors.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"id": "D1",
"platform": "dummy",
"type": "slider",
"description": "Entrance door",
"friendly_name": "Entrance door",
"placement": "R1",
"con_id": "DC1",
"con_params": {
Expand All @@ -14,7 +14,7 @@
"id": "D2",
"platform": "dummy",
"type": "slider",
"description": "to bedroom",
"friendly_name": "Bedroom door",
"placement": "R4",
"con_id": "DC1",
"con_params": {
Expand All @@ -25,7 +25,7 @@
"id": "D3",
"platform": "dummy",
"type": "slider",
"description": "to office",
"friendly_name": "Office door",
"placement": "R5",
"con_id": "DC1",
"con_params": {
Expand Down
2 changes: 1 addition & 1 deletion samples/config/things/fans.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"id": "F1",
"platform": "dummy",
"type": "switch",
"description": "",
"friendly_name": "Kitchen cooker hood",
"placement": "R2",
"con_id": "DC1",
"con_params": {
Expand Down
12 changes: 6 additions & 6 deletions samples/config/things/lighting.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"id": "Li1",
"platform": "dummy",
"type": "switch",
"description": "",
"friendly_name": "",
"placement": "R1",
"con_id": "DC1",
"con_params": {
Expand All @@ -14,7 +14,7 @@
"id": "Li2",
"platform": "dummy",
"type": "switch",
"description": "",
"friendly_name": "",
"placement": "R2",
"con_id": "DC1",
"con_params": {
Expand All @@ -25,7 +25,7 @@
"id": "Li3",
"platform": "dummy",
"type": "switch",
"description": "",
"friendly_name": "",
"placement": "R3",
"con_id": "DC1",
"con_params": {
Expand All @@ -36,7 +36,7 @@
"id": "Li4",
"platform": "dummy",
"type": "switch",
"description": "",
"friendly_name": "",
"placement": "R4",
"con_id": "DC1",
"con_params": {
Expand All @@ -47,7 +47,7 @@
"id": "Li5",
"platform": "dummy",
"type": "switch",
"description": "",
"friendly_name": "",
"placement": "R4",
"con_id": "DC1",
"con_params": {
Expand All @@ -58,7 +58,7 @@
"id": "Li6",
"platform": "dummy",
"type": "switch",
"description": "",
"friendly_name": "",
"placement": "R6",
"con_id": "DC1",
"con_params": {
Expand Down
2 changes: 1 addition & 1 deletion samples/config/things/players.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"id": "PLAY1",
"platform": "dummy",
"type": "player",
"description": "Default player",
"friendly_name": "Living room default player",
"placement": "R6",
"con_id": "DC2",
"con_params": {
Expand Down
8 changes: 4 additions & 4 deletions samples/config/things/sunblinds.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"id": "SB1",
"platform": "dummy",
"type": "slider",
"description": "Kitchen",
"friendly_name": "Kitchen sunblind",
"placement": "R2",
"con_id": "DC1",
"con_params": {
Expand All @@ -14,7 +14,7 @@
"id": "SB2",
"platform": "dummy",
"type": "slider",
"description": "Bedroom",
"friendly_name": "Bedroom sunblind",
"placement": "R4",
"con_id": "DC1",
"con_params": {
Expand All @@ -25,7 +25,7 @@
"id": "SB3",
"platform": "dummy",
"type": "slider",
"description": "Office",
"friendly_name": "Office sunblind",
"placement": "R5",
"con_id": "DC1",
"con_params": {
Expand All @@ -36,7 +36,7 @@
"id": "SB4",
"platform": "dummy",
"type": "slider",
"description": "Living Room",
"friendly_name": "Living Room sunblind",
"placement": "R6",
"con_id": "DC1",
"con_params": {
Expand Down

0 comments on commit 018a21c

Please sign in to comment.