aio-libs / aiomonitor

aiomonitor is module that adds monitor and python REPL capabilities for asyncio application

Home Page:https://aiomonitor.aio-libs.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

console command: AttributeError: '_SpecialForm' object has no attribute 'setdefault'

rhiller opened this issue · comments

Test program:

#!/usr/bin/env python

import asyncio
import aiomonitor

async def amain():
    while True:
        await asyncio.sleep(5)
        print('async ticking')

loop = asyncio.get_event_loop()
with aiomonitor.start_monitor(loop):
    loop.run_until_complete(amain())

While this is running, I connect to it with: nc localhost 50101 and type console. Immediate crash with:

Task exception was never retrieved
future: <Task finished coro=<handle_connect() done, defined at /home/abc/venv/lib/python3.7/site-packages/aioconsole/server.py:8> exception=AttributeError("'_SpecialForm' object has no attribute 'setdefault'")>
Traceback (most recent call last):
  File "/home/abc/venv/lib/python3.7/site-packages/aioconsole/server.py", line 11, in handle_connect
    interface = factory(streams=streams)
  File "/home/abc/venv/lib/python3.7/site-packages/aiomonitor/utils.py", line 73, in _factory
    locals=locals, streams=streams, loop=loop)
  File "/home/abc/venv/lib/python3.7/site-packages/aioconsole/code.py", line 56, in __init__
    self.locals.setdefault('asyncio', asyncio)
  File "/usr/lib/python3.7/typing.py", line 698, in __getattr__
    return getattr(self.__origin__, attr)
AttributeError: '_SpecialForm' object has no attribute 'setdefault'

Python 3.7.1
aioconsole 0.1.11
aiomonitor 0.3.1
uvloop not installed
Linux

@jettify would you take a look?

Works for me locally, tried your script with nc:

$ nc localhost 50101

Asyncio Monitor: 1 task running
Type help for available commands

monitor >>> console
Python 3.7.2 (default, Dec 27 2018, 07:35:06)
[Clang 10.0.0 (clang-1000.11.45.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
---
This console is running in an asyncio event loop.
It allows you to wait for coroutines using the 'await' syntax.
Try: await asyncio.sleep(1, result=3)
---
>>> import asyncio
>>> await asyncio.sleep(0.1)
>>>

Only difference, I have Python 3.7.2 and macOS

May be clean virtual env can help?

My initial test (above) was done on a Raspberry Pi.

The following tests were all done with fresh virtual envs.

I just did a build from source of python3.7.2 on an AWS Amazon Linux machine. I get the same result:

Task exception was never retrieved
future: <Task finished coro=<handle_connect() done, defined at /home/abc/aiomon372/lib/python3.7/site-packages/aioconsole/server.py:8> exception=AttributeError("'_SpecialForm' object has no attribute 'setdefault'")>
Traceback (most recent call last):
  File "/home/abc/aiomon372/lib/python3.7/site-packages/aioconsole/server.py", line 11, in handle_connect
    interface = factory(streams=streams)
  File "/home/abc/aiomon372/lib/python3.7/site-packages/aiomonitor/utils.py", line 73, in _factory
    locals=locals, streams=streams, loop=loop)
  File "/home/abc/aiomon372/lib/python3.7/site-packages/aioconsole/code.py", line 56, in __init__
    self.locals.setdefault('asyncio', asyncio)
  File "/usr/local/lib/python3.7/typing.py", line 698, in __getattr__
    return getattr(self.__origin__, attr)
AttributeError: '_SpecialForm' object has no attribute 'setdefault'

Python 3.7.2
aioconsole 0.1.11
aiomonitor 0.3.1

I also tried with Python 3.6.5 on an AWS Amazon Linux machine and get nearly the same result:

Task exception was never retrieved
future: <Task finished coro=<handle_connect() done, defined at /home/abc/aiomon/lib/python3.6/site-packages/aioconsole/server.py:8> exception=AttributeError("'_Union' object has no attribute 'setdefault'",)>
Traceback (most recent call last):
  File "/home/abc/aiomon/lib/python3.6/site-packages/aioconsole/server.py", line 11, in handle_connect
    interface = factory(streams=streams)
  File "/home/abc/aiomon/lib/python3.6/site-packages/aiomonitor/utils.py", line 73, in _factory
    locals=locals, streams=streams, loop=loop)
  File "/home/abc/aiomon/lib/python3.6/site-packages/aioconsole/code.py", line 56, in __init__
    self.locals.setdefault('asyncio', asyncio)
AttributeError: '_Union' object has no attribute 'setdefault'

The difference being the AttributeError on _Union versus _SpecialForm.

Python 3.6.5
aioconsole 0.1.11
aiomonitor 0.3.1

Perhaps a clue is that when I connect with nc when running the Python 3.7.2 test, I see:

$ nc localhost 50101

Asyncio Monitor: 2 tasks running
Type help for commands
monitor >>> ps
+-----------------+----------+----------------------------------------------------------------------------+
| Task ID         | State    | Task                                                                       |
+-----------------+----------+----------------------------------------------------------------------------+
| 140306876217288 | PENDING  | <Task pending coro=<amain() running at wss6:8> wait_for=<Future pending    |
|                 |          | cb=[<TaskWakeupMethWrapper object at 0x7f9bbcd8a1c8>()]>                   |
|                 |          | cb=[_run_until_complete_cb() at                                            |
|                 |          | /usr/local/lib/python3.7/asyncio/base_events.py:158]>                      |
| 140306876217448 | FINISHED | <Task finished coro=<start_interactive_server() done, defined at           |
|                 |          | /home/abc/aiomon372/lib/python3.7/site-packages/aioconsole/server.py:17> |
|                 |          | result=<Server socke....1', 50102)>]>>                                     |
+-----------------+----------+----------------------------------------------------------------------------+
monitor >>>

Your example only shows one task. I notice that all of my tests (Raspberry Pi with Python 3.7.1, and Python 3.6.5) show two tasks.

Can confirm this.

$ python -V
Python 3.6.6
$ pip freeze
aioconsole==0.1.11
aiomonitor==0.3.1
terminaltables==3.1.0

Clean virtualenv. Investigating.

This issue was introduced in: 0b71c7f#diff-51363086d2299da2efead1b3d155a45bR32 (notice locals assigment) and presents in 0.3.1 release, but not on master. How about make a new year release? (:

I confirm that locals=None works as a workaround.

as in:

loop = asyncio.get_event_loop()
with aiomonitor.start_monitor(loop, locals=None):
    loop.run_until_complete(amain())

I probably contaminated my env with master version, as result failed to repro... Anyway new release should fix things.

🎉 🎅