aiopoc.py 1.5KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. import asyncio
  2. import json
  3. from sh import tail
  4. from asyncio import sleep
  5. from aiohttp import web
  6. import marshmallow
  7. from hapic import async as hapic
  8. from hapic.ext.aiohttp.context import AiohttpContext
  9. class OutputStreamItemSchema(marshmallow.Schema):
  10. i = marshmallow.fields.Integer(required=True)
  11. # Python 3.6 async generator: http://rickyhan.com/jekyll/update/2018/01/27/python36.html
  12. # Python 3.5 solution: https://stackoverflow.com/questions/37549846/how-to-use-yield-inside-async-function
  13. class LinesAsyncGenerator:
  14. def __init__(self):
  15. self.iterable = tail("-f", "aiopocdata.txt", _iter=True)
  16. async def __aiter__(self):
  17. return self
  18. async def __anext__(self):
  19. line = next(self.iterable)
  20. if 'STOP' in line:
  21. raise StopAsyncIteration
  22. await asyncio.sleep(0.025)
  23. return json.loads(line)
  24. @hapic.with_api_doc()
  25. @hapic.output_stream(item_schema=OutputStreamItemSchema())
  26. def handle(request):
  27. # response = web.StreamResponse(
  28. # status=200,
  29. # reason='OK',
  30. # headers={
  31. # 'Content-Type': 'text/plain; charset=utf-8',
  32. # },
  33. # )
  34. #
  35. # await response.prepare(request)
  36. # response.enable_chunked_encoding()
  37. # for line in tail("-f", "aiopocdata.txt", _iter=True):
  38. # await response.write(line.encode('utf-8'))
  39. # await sleep(0.1)
  40. # return response
  41. return LinesAsyncGenerator()
  42. app = web.Application()
  43. app.add_routes([
  44. web.get('/', handle)
  45. ])
  46. hapic.set_context(AiohttpContext(app))
  47. web.run_app(app)