ussserrr / stm32pio

Automate managing of STM32CubeMX + PlatformIO projects
https://pypi.org/project/stm32pio
Other
224 stars 24 forks source link

Migrate to async/await #65

Open ussserrr opened 3 years ago

ussserrr commented 3 years ago

Return some kind of a "remote controller" to control the running action. See PoC:

import asyncio
import collections
import time

class Project:
    async def build(self):
        print('started')
        proc = await asyncio.create_subprocess_exec('sh', 'cmd.sh', stdout=asyncio.subprocess.PIPE)
        try:
            while (line := await proc.stdout.readline()) != b'':
                print(line.decode(), end='')
            # await proc.wait()
            # if proc.returncode != 0:
            #     raise Exception('process errored (placeholder exception)')
        except asyncio.CancelledError as e:
            proc.terminate()
            print('process terminated:', e)
        return proc.returncode

async def cli_main():
    proj = Project()
    await proj.build()

async def worker(queue: asyncio.Queue):
    while True:
        action = await queue.get()
        await action
        queue.task_done()

class Queue(asyncio.Queue):
    def __init__(self):
        super().__init__()
        self.container = []
        self.worker = asyncio.create_task(self.loop())
        self.current_action = None

    async def loop(self):
        while True:
            result = await self.get()
            print(result)
            self.current_action = asyncio.create_task(result)
            await self.current_action
            self.task_done()

    def put_nowait(self, item) -> None:
        self.container.append(item)
        return super().put_nowait(item)

    async def get(self):
        result = await super().get()
        self.container.pop(0)
        return result

    async def cancel(self, msg=None):
        if self.current_action is not None:
            self.current_action.cancel(msg)
        for _ in range(len(self.container)):
            self.container.pop()
            await self.get()
            self.task_done()

class Wrapper:
    def __init__(self):
        self.project = Project()
        self.queue = Queue()

    def run(self, action, *args):
        action = getattr(self.project, action)(*args)
        self.queue.put_nowait(action)
        # await action

async def gui_main():
    gui_proj = Wrapper()
    gui_proj.run('build')
    print('A')
    gui_proj.run('build')
    print('B')
    await asyncio.sleep(3)
    await gui_proj.queue.cancel(msg='hvatit')

mode = 'GUI'

print(mode)
if mode == 'CLI':
    asyncio.run(cli_main())
elif mode == 'GUI':
    asyncio.run(gui_main())
for i in {1..20}; do
  echo "$i"
  sleep 0.5
done

# java_not_exist hello world

Important: asyncio library is still under heavy and rapid development so actualize all your initial suggestions/thoughts before proceeding.