Skip to content

Commit

Permalink
Store XML-node at UpnpDevice/UpnpService/UpnpAction/UpnpAction.Argume…
Browse files Browse the repository at this point in the history
…nt/UpnpStateVariable
  • Loading branch information
StevenLooman committed Dec 9, 2018
1 parent 81c4dc7 commit 4e490f0
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 13 deletions.
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Changes
0.13.5 (unreleased)

- Minor refactorings: less private variables which are actually public (through properties) anyway
- Store XML-node at UpnpDevice/UpnpService/UpnpAction/UpnpAction.Argument/UpnpStateVariable


0.13.4 (2018-12-07)
Expand Down
37 changes: 24 additions & 13 deletions async_upnp_client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ class UpnpEventHandler:
subscribe/resubscribe/unsubscribe handle subscriptions.
"""

def __init__(self, callback_url: str, requester: UpnpRequester) -> None:
def __init__(self, callback_url: str, requester: UpnpRequester):
"""Initializer."""
self._callback_url = callback_url
self._requester = requester
Expand Down Expand Up @@ -317,11 +317,12 @@ class UpnpDevice:
"""UPnP Device representation."""

def __init__(self, requester: UpnpRequester, device_description: Mapping,
services: List['UpnpService']) -> None:
services: List['UpnpService'], xml: ET.Element) -> None:
"""Initializer."""
self.requester = requester
self._device_description = device_description
self.services = {service.service_type: service for service in services}
self.xml = xml

# bind services to ourselves
for service in services:
Expand Down Expand Up @@ -361,13 +362,15 @@ class UpnpService:
# pylint: disable=too-many-instance-attributes

def __init__(self, requester: UpnpRequester, service_description: Mapping,
state_variables: List['UpnpStateVariable'], actions: List['UpnpAction']) -> None:
state_variables: List['UpnpStateVariable'], actions: List['UpnpAction'],
xml: ET.Element) -> None:
"""Initializer."""
# pylint: disable=too-many-arguments
self.requester = requester
self._service_description = service_description
self.state_variables = {sv.name: sv for sv in state_variables}
self.actions = {ac.name: ac for ac in actions}
self.xml = xml

self.on_event = None
self._device = None
Expand Down Expand Up @@ -487,11 +490,13 @@ class Argument:
"""Representation of an Argument of an Action."""

def __init__(self, name: str, direction: str,
related_state_variable: 'UpnpStateVariable') -> None:
related_state_variable: 'UpnpStateVariable',
xml: ET.Element) -> None:
"""Initializer."""
self.name = name
self.direction = direction
self.related_state_variable = related_state_variable
self.xml = xml
self._value = None

def validate_value(self, value):
Expand Down Expand Up @@ -527,10 +532,12 @@ def coerce_upnp(self, value) -> str:
"""Coerce Python value to UPnP value."""
return self.related_state_variable.coerce_upnp(value)

def __init__(self, name: str, arguments) -> None:
def __init__(self, name: str, arguments: List['UpnpAction.UpnpArgument'],
xml: ET.Element) -> None:
"""Initializer."""
self.name = name
self.arguments = arguments
self.xml = xml

self._service = None

Expand Down Expand Up @@ -673,10 +680,11 @@ class UpnpStateVariable:

UPNP_VALUE_ERROR = object()

def __init__(self, state_variable_info: Mapping, schema) -> None:
def __init__(self, state_variable_info: Mapping, schema, xml) -> None:
"""Initializer."""
self._state_variable_info = state_variable_info
self._schema = schema
self.xml = xml

self._service = None
self._value = None
Expand Down Expand Up @@ -860,11 +868,11 @@ def __init__(self, requester, disable_state_variable_validation=False):
'disable_state_variable_validation': disable_state_variable_validation,
}

async def async_create_device(self, description_url) -> UpnpDevice:
async def async_create_device(self, description_url: str) -> UpnpDevice:
"""Create a UpnpDevice, with all of it UpnpServices."""
root = await self._async_get_url_xml(description_url)

# get name
# get device info
device_desc = self._device_parse_xml(root, description_url)

# get services
Expand All @@ -873,7 +881,7 @@ async def async_create_device(self, description_url) -> UpnpDevice:
service = await self.async_create_service(service_desc_xml, description_url)
services.append(service)

return UpnpDevice(self.requester, device_desc, services)
return UpnpDevice(self.requester, device_desc, services, root)

def _device_parse_xml(self, device_description_xml: ET.Element, description_url: str) -> Dict:
"""Parse device description XML."""
Expand Down Expand Up @@ -908,7 +916,8 @@ def create_service(self,
state_vars = self.create_state_variables(scpd_xml)
actions = self.create_actions(scpd_xml, state_vars)

return UpnpService(self.requester, service_description, state_vars, actions)
return UpnpService(self.requester, service_description, state_vars, actions,
service_description_xml)

def _service_parse_xml(self, service_description_xml: ET.Element) -> Dict:
"""Parse service description XML."""
Expand All @@ -934,7 +943,7 @@ def create_state_variable(self, state_variable_xml: ET.Element) -> UpnpStateVari
state_variable_info = self._state_variable_parse_xml(state_variable_xml)
type_info = state_variable_info['type_info']
schema = self._state_variable_create_schema(type_info)
return UpnpStateVariable(state_variable_info, schema)
return UpnpStateVariable(state_variable_info, schema, state_variable_xml)

def _state_variable_parse_xml(self, state_variable_xml: ET.Element) -> Dict:
"""Parse XML for state variable."""
Expand Down Expand Up @@ -1038,9 +1047,10 @@ def create_action(self, action_xml: ET.Element, state_variables: List[UpnpStateV
action_info = self._action_parse_xml(action_xml, state_variables)
args = [UpnpAction.Argument(arg_info['name'],
arg_info['direction'],
arg_info['state_variable'])
arg_info['state_variable'],
arg_info['xml'])
for arg_info in action_info['arguments']]
return UpnpAction(action_info['name'], args)
return UpnpAction(action_info['name'], args, action_xml)

def _action_parse_xml(self, action_xml: ET.Element, state_variables: List[UpnpStateVariable]) \
-> Dict:
Expand All @@ -1057,6 +1067,7 @@ def _action_parse_xml(self, action_xml: ET.Element, state_variables: List[UpnpSt
'name': argument_xml.find('service:name', NS).text,
'direction': argument_xml.find('service:direction', NS).text,
'state_variable': svs[state_variable_name],
'xml': argument_xml,
}
info['arguments'].append(argument)
return info
Expand Down
25 changes: 25 additions & 0 deletions tests/test_upnp_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,31 @@ async def test_init(self):
state_var = service.state_variable('Volume')
assert state_var

action = service.action('GetVolume')
assert action

argument = action.argument('InstanceID')
assert argument

@pytest.mark.asyncio
async def test_init_xml(self):
r = UpnpTestRequester(RESPONSE_MAP)
factory = UpnpFactory(r)
device = await factory.async_create_device('http://localhost:1234/dmr')
assert device.xml is not None

service = device.service('urn:schemas-upnp-org:service:RenderingControl:1')
assert service.xml is not None

state_var = service.state_variable('Volume')
assert state_var.xml is not None

action = service.action('GetVolume')
assert action.xml is not None

argument = action.argument('InstanceID')
assert argument.xml is not None

@pytest.mark.asyncio
async def test_set_value_volume(self):
r = UpnpTestRequester(RESPONSE_MAP)
Expand Down

0 comments on commit 4e490f0

Please sign in to comment.