Skip to content

Commit

Permalink
Merge pull request #61 from newAM/master
Browse files Browse the repository at this point in the history
Update asyncio syntax and add a changelog.
  • Loading branch information
newAM authored Sep 28, 2020
2 parents a13a13a + bc9ea68 commit c598e0e
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 45 deletions.
39 changes: 39 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
Change Log
##########

`Unreleased`_
*************
Added
=====
- Added a changelog.
- Added Python 3.8 testing.

Changed
=======
- Updated PyPi classifiers.
- Updated asyncio syntax to use ``await`` and ``async def``.

Deprecated
==========

Removed
=======
- Drop Python 3.4 support (EOL).

Fixed
=====
- Allow ``TcpAdapter`` to recover from a lost connection.
- Added a missing ``await`` for an ``asyncio.sleep``.
- Fixed long_description field for PyPi releases, the README will now render.

Security
========

`0.4.14`_ 2020-09-27
********************
Changed
=======
- Removed `typing` requirement.

.. _Unreleased: https://github.com/konikvranik/pyCEC/compare/v0.4.14..HEAD
.. _0.4.14: https://github.com/konikvranik/pyCEC/releases/tag/v0.4.14
5 changes: 2 additions & 3 deletions pycec/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,12 @@
from .network import HDMINetwork


@asyncio.coroutine
def async_show_devices(network, loop):
async def async_show_devices(network, loop):
while True:
for d in network.devices:
_LOGGER.debug("Present device %s", d)
yield
yield from asyncio.sleep(10, loop=loop)
await asyncio.sleep(10, loop=loop)


def main():
Expand Down
68 changes: 27 additions & 41 deletions pycec/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,26 +169,23 @@ def is_off(self):
def turn_on(self): # pragma: no cover
self._loop.create_task(self.async_turn_on())

@asyncio.coroutine
def async_turn_on(self): # pragma: no cover
async def async_turn_on(self): # pragma: no cover
command = CecCommand(0x44, self.logical_address, att=[0x6d])
yield from self.async_send_command(command)
await self.async_send_command(command)

def turn_off(self): # pragma: no cover
self._loop.create_task(self.async_turn_off())

@asyncio.coroutine
def async_turn_off(self): # pragma: no cover
async def async_turn_off(self): # pragma: no cover
command = CecCommand(0x44, self.logical_address, att=[0x6c])
yield from self.async_send_command(command)
await self.async_send_command(command)

def toggle(self): # pragma: no cover
self._loop.create_task(self.async_toggle())

@asyncio.coroutine
def async_toggle(self): # pragma: no cover
async def async_toggle(self): # pragma: no cover
command = CecCommand(0x44, self.logical_address, att=[0x40])
yield from self.async_send_command(command)
await self.async_send_command(command)

@property
def type(self):
Expand Down Expand Up @@ -241,37 +238,34 @@ def task(self):
def task(self, task):
self._task = task

@asyncio.coroutine
def async_run(self):
async def async_run(self):
_LOGGER.debug("Starting device %d", self.logical_address)
while not self._stop:
for prop in UPDATEABLE:
if not self._stop:
yield from self.async_request_update(prop[0])
await self.async_request_update(prop[0])
start_time = self._loop.time()
while not self._stop and self._loop.time() <= (
start_time + self._update_period
):
yield from asyncio.sleep(0.3, loop=self._loop)
await asyncio.sleep(0.3, loop=self._loop)
_LOGGER.info("HDMI device %s stopped.", self) # pragma: no cover

def stop(self): # pragma: no cover
_LOGGER.debug("HDMI device %s stopping", self)
self._stop = True

@asyncio.coroutine
def async_request_update(self, cmd: int):
async def async_request_update(self, cmd: int):
self._updates[cmd] = False
command = CecCommand(cmd)
yield from self.async_send_command(command)
await self.async_send_command(command)

def send_command(self, command):
self._loop.create_task(self.async_send_command(command))

@asyncio.coroutine
def async_send_command(self, command: CecCommand):
async def async_send_command(self, command: CecCommand):
command.dst = self._logical_address
yield from self._network.async_send_command(command)
await self._network.async_send_command(command)

def active_source(self):
self._loop.create_task(
Expand Down Expand Up @@ -306,7 +300,7 @@ def __init__(self, adapter: AbstractCecAdapter,
if self._managed_loop:
self._loop = asyncio.new_event_loop()
else:
_LOGGER.warn("Be aware! Network is using shared event loop!")
_LOGGER.warning("Be aware! Network is using shared event loop!")
self._loop = loop
self._adapter = adapter
self._adapter.set_event_loop(self._loop)
Expand All @@ -326,8 +320,7 @@ def initialized(self):
def init(self):
self._loop.create_task(self.async_init())

@asyncio.coroutine
def async_init(self):
async def async_init(self):
_LOGGER.debug("initializing") # pragma: no cover
_LOGGER.debug("setting callback") # pragma: no cover
self._adapter.set_command_callback(self.command_callback)
Expand All @@ -336,7 +329,7 @@ def async_init(self):
self._running = True
while not (task.done() or task.cancelled()) and self._running:
_LOGGER.debug("Init pending - %s", task) # pragma: no cover
yield from asyncio.sleep(1, loop=self._loop)
await asyncio.sleep(1, loop=self._loop)
_LOGGER.debug("Init done") # pragma: no cover

def scan(self):
Expand All @@ -359,22 +352,19 @@ def _after_polled(self, device, task):
self._devices[device])
del (self._devices[device])

@asyncio.coroutine
def async_scan(self):
async def async_scan(self):
_LOGGER.info("Looking for new devices...")
if not self.initialized:
_LOGGER.error("Device not initialized!!!") # pragma: no cover
return
for d in range(15):
task = self._adapter.poll_device(d)
task.add_done_callback(functools.partial(self._after_polled, d))
yield

def send_command(self, command):
self._loop.create_task(self.async_send_command(command))

@asyncio.coroutine
def async_send_command(self, command):
async def async_send_command(self, command):
if isinstance(command, str):
command = CecCommand(command)
_LOGGER.debug("<< %s", command)
Expand All @@ -385,27 +375,24 @@ def async_send_command(self, command):
def standby(self):
self._loop.create_task(self.async_standby())

@asyncio.coroutine
def async_standby(self):
async def async_standby(self):
_LOGGER.debug("Queuing system standby") # pragma: no cover
self._loop.call_soon_threadsafe(self._adapter.standby_devices)

def power_on(self):
self._loop.create_task(self.async_power_on())

@asyncio.coroutine
def async_power_on(self):
async def async_power_on(self):
_LOGGER.debug("Queuing power on") # pragma: no cover
self._loop.call_soon_threadsafe(self._adapter.power_on_devices)

def active_source(self, source: PhysicalAddress):
self._loop.create_task(self.async_active_source(source))

@asyncio.coroutine
def async_active_source(self, addr: PhysicalAddress):
yield from self.async_send_command(
async def async_active_source(self, addr: PhysicalAddress):
await self.async_send_command(
CecCommand(CMD_ACTIVE_SOURCE, ADDR_BROADCAST, att=addr.asattr))
yield from self.async_send_command(
await self.async_send_command(
CecCommand(CMD_STREAM_PATH, ADDR_BROADCAST, att=addr.asattr))

@property
Expand All @@ -415,26 +402,25 @@ def devices(self) -> tuple:
def get_device(self, i) -> HDMIDevice:
return self._devices.get(i, None)

@asyncio.coroutine
def async_watch(self, loop=None):
async def async_watch(self, loop=None):
_LOGGER.debug("Start watching...") # pragma: no cover
if loop is None:
loop = self._loop
_LOGGER.debug("loop: %s", loop)
while self._running:
if self.initialized:
_LOGGER.debug("Scanning...") # pragma: no cover
yield from self.async_scan()
await self.async_scan()
_LOGGER.debug("Sleep...") # pragma: no cover
start_time = self._loop.time()
while (
self._loop.time() <= (start_time + self._scan_interval)
and self._running
):
yield from asyncio.sleep(0.3, loop=loop)
await asyncio.sleep(0.3, loop=loop)
else:
_LOGGER.warning("Not initialized. Waiting for init.")
yield from asyncio.sleep(1, loop=loop)
await asyncio.sleep(1, loop=loop)
_LOGGER.info("No watching anymore")

def start(self):
Expand Down
1 change: 0 additions & 1 deletion requirements.txt

This file was deleted.

6 changes: 6 additions & 0 deletions tests/datastruct/test_physical_address.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import pytest
from pycec.network import PhysicalAddress


Expand Down Expand Up @@ -53,3 +54,8 @@ def test_str():
assert ("%s" % pa) == "0.0.0.0"
pa = PhysicalAddress("00:10")
assert ("%s" % pa) == "0.0.1.0"


def test_raises():
with pytest.raises(AttributeError):
PhysicalAddress([0] * 8)

0 comments on commit c598e0e

Please sign in to comment.