Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NameError: name 'BRIDGE' is not defined #15

Closed
babolivier opened this issue Mar 27, 2020 · 11 comments · Fixed by #36
Closed

NameError: name 'BRIDGE' is not defined #15

babolivier opened this issue Mar 27, 2020 · 11 comments · Fixed by #36
Labels
bug Something isn't working

Comments

@babolivier
Copy link

Running mirage right after installing it on my Archlinux setup causes an infinite spinner and prints the following in the following to be printed in the terminal:

Got library name:  "/usr/lib/qt/qml/io/thp/pyotherside/libpyothersideplugin.so"
"PyOtherSide error: Traceback (most recent call last):\n\n  File \"src/backend/qml_bridge.py\", line 148, in <module>\n    BRIDGE = QMLBridge()\n\n  File \"src/backend/qml_bridge.py\", line 43, in __init__\n    from .backend import Backend\n\n  File \"src/backend/backend.py\", line 15, in <module>\n    from .matrix_client import MatrixClient\n\n  File \"src/backend/matrix_client.py\", line 39, in <module>\n    from .media_cache import Media, Thumbnail\n\n  File \"src/backend/media_cache.py\", line 30, in <module>\n    CONCURRENT_DOWNLOADS_LIMIT                   = asyncio.BoundedSemaphore(8)\n\n  File \"/usr/lib/python3.8/asyncio/locks.py\", line 529, in __init__\n    super().__init__(value, loop=loop)\n\n  File \"/usr/lib/python3.8/asyncio/locks.py\", line 458, in __init__\n    self._loop = events.get_event_loop()\n\n  File \"/usr/lib/python3.8/asyncio/events.py\", line 639, in get_event_loop\n    raise RuntimeError('There is no current event loop in thread %r.'\n\nRuntimeError: There is no current event loop in thread 'Dummy-1'.\n"
Unhandled PyOtherSide error: Cannot import module: backend.qml_bridge (Traceback (most recent call last):

  File "src/backend/qml_bridge.py", line 148, in <module>
    BRIDGE = QMLBridge()

  File "src/backend/qml_bridge.py", line 43, in __init__
    from .backend import Backend

  File "src/backend/backend.py", line 15, in <module>
    from .matrix_client import MatrixClient

  File "src/backend/matrix_client.py", line 39, in <module>
    from .media_cache import Media, Thumbnail

  File "src/backend/media_cache.py", line 30, in <module>
    CONCURRENT_DOWNLOADS_LIMIT                   = asyncio.BoundedSemaphore(8)

  File "/usr/lib/python3.8/asyncio/locks.py", line 529, in __init__
    super().__init__(value, loop=loop)

  File "/usr/lib/python3.8/asyncio/locks.py", line 458, in __init__
    self._loop = events.get_event_loop()

  File "/usr/lib/python3.8/asyncio/events.py", line 639, in get_event_loop
    raise RuntimeError('There is no current event loop in thread %r.'

RuntimeError: There is no current event loop in thread 'Dummy-1'.
)
"PyOtherSide error: Traceback (most recent call last):\n\n  File \"<string>\", line 1, in <module>\n\nNameError: name 'BRIDGE' is not defined\n"
Unhandled PyOtherSide error: Function not found: 'BRIDGE.call_backend_coro' (Traceback (most recent call last):

  File "<string>", line 1, in <module>

NameError: name 'BRIDGE' is not defined
)
@mirukana
Copy link
Owner

Can you the event-loop-fix branch to see if it fixes the issue?

@mirukana mirukana added the bug Something isn't working label Mar 28, 2020
@babolivier
Copy link
Author

Right, I think I figured it out - looks like it was because I installed everything in a virtualenv.
I've re-run the install process outside of it and it works fine now.

@Amolith
Copy link

Amolith commented Apr 9, 2020

Mirage is crashing for me as well and I get a somewhat similar traceback; I didn't think it warranted its own issue because it looks like the core problem is the same. I installed it with the AUR package.

❯ mirage
Got library name:  "/usr/lib/qt/qml/io/thp/pyotherside/libpyothersideplugin.so"
"PyOtherSide error: Traceback (most recent call last):\n\n  File \"qrc:/src/backend/qml_bridge.py\", line 19, in <module>\n    from .pyotherside_events import CoroutineDone, LoopException\n\n  File \"qrc:/src/backend/pyotherside_events.py\", line 8, in <module>\n    from .utils import serialize_value_for_qml\n\n  File \"qrc:/src/backend/utils.py\", line 24, in <module>\n    import filetype\n\nModuleNotFoundError: No module named 'filetype'\n"
Unhandled PyOtherSide error: Cannot import module: backend.qml_bridge (Traceback (most recent call last):

  File "qrc:/src/backend/qml_bridge.py", line 19, in <module>
    from .pyotherside_events import CoroutineDone, LoopException

  File "qrc:/src/backend/pyotherside_events.py", line 8, in <module>
    from .utils import serialize_value_for_qml

  File "qrc:/src/backend/utils.py", line 24, in <module>
    import filetype

ModuleNotFoundError: No module named 'filetype'
)
"PyOtherSide error: Traceback (most recent call last):\n\n  File \"<string>\", line 1, in <module>\n\nNameError: name 'BRIDGE' is not defined\n"
Unhandled PyOtherSide error: Function not found: 'BRIDGE.call_backend_coro' (Traceback (most recent call last):

  File "<string>", line 1, in <module>

NameError: name 'BRIDGE' is not defined

@mirukana
Copy link
Owner

Can you post the output of these?

python3 -c 'import filetype; print(filetype)'

And in <mirage repo root>/src/backend/qml_bridge.py, add this to the top before any import statement:

import sys; print(sys.path)

Then start mirage with:

make clean; qmake mirage.pro CONFIG+= dev && make && ./mirage

@mirukana mirukana reopened this Apr 10, 2020
@DataBeaver
Copy link
Contributor

I got the error mentioned in the original report and also had some Python packages installed in virtualenv (those not available in Debian unstable). I'm not sure how virtualenv affects it, but there seems to be something funny about threads. Apparently the Python bridge thread is not the main application thread so the asyncio module does not install a default event loop. I was able to fix it with:

--- a/src/backend/qml_bridge.py
+++ b/src/backend/qml_bridge.py
@@ -25,6 +25,11 @@ except ModuleNotFoundError:
 else:
     uvloop.install()
 
+try:
+    asyncio.get_event_loop()
+except RuntimeError:
+    asyncio.set_event_loop(asyncio.new_event_loop())
+
 
 class QMLBridge:
     """Setup asyncio and provide synchronous methods to call coroutines.

However I'm then getting a bunch of various QML errors and messages are not displayed, but I think that's a different issue.

@mirukana
Copy link
Owner

mirukana commented May 15, 2020

The error shouldn't be the same unless you run an old version of Mirage, can you post the full traceback?
QMLBridge.__init__() already creates an asyncio loop and does start a thread to handle coroutine calls from QML, which sets its own loop to the one created in __init__(), so it wouldn't make sense to create one before the class like this.

@DataBeaver
Copy link
Contributor

Unhandled PyOtherSide error: Cannot import module: backend.qml_bridge (Traceback (most recent call last):

  File "qrc:/src/backend/qml_bridge.py", line 153, in <module>
    BRIDGE = QMLBridge()

  File "qrc:/src/backend/qml_bridge.py", line 48, in __init__
    from .backend import Backend

  File "qrc:/src/backend/backend.py", line 15, in <module>
    from .matrix_client import MatrixClient

  File "qrc:/src/backend/matrix_client.py", line 40, in <module>
    from .media_cache import Media, Thumbnail

  File "qrc:/src/backend/media_cache.py", line 30, in <module>
    CONCURRENT_DOWNLOADS_LIMIT                   = asyncio.BoundedSemaphore(8)

  File "/usr/lib/python3.8/asyncio/locks.py", line 529, in __init__
    super().__init__(value, loop=loop)

  File "/usr/lib/python3.8/asyncio/locks.py", line 458, in __init__
    self._loop = events.get_event_loop()

  File "/usr/lib/python3.8/asyncio/events.py", line 639, in get_event_loop
    raise RuntimeError('There is no current event loop in thread %r.'

RuntimeError: There is no current event loop in thread 'Dummy-1'.

QMLBridge.init does not explicitly create an asyncio event loop; it relies on get_event_loop implicitly creating one. According to the documentation that only happens if the OS thread is main, which apparently is not the case here. Using strace I can see that the process starts with pid 24064 but the exception gets printed from pid 24066.

Furthermore, as can be seen in the traceback, a few calls down from the import Backend line there's an attempt to create a semaphore, which wants to attach itself to the event loop of the current thread. This happens before even the get_event_loop call in QMLBridge.init.

My patch attempts to do the same get_event_loop() call and if it doesn't succeed, it explicitly creates a new event loop and sets it for the current thread. The exact placement of these lines does not really matter as long as they happen before the import Backend call. Here's an alternative version:

--- a/src/backend/qml_bridge.py
+++ b/src/backend/qml_bridge.py
@@ -40,12 +40,16 @@ class QMLBridge:
     """
 
     def __init__(self) -> None:
+        try:
+            self._loop = asyncio.get_event_loop()
+        except RuntimeError:
+            self._loop = asyncio.new_event_loop()
+            asyncio.set_event_loop(self._loop)
+        self._loop.set_exception_handler(self._loop_exception_handler)
+
         from .backend import Backend
         self.backend: Backend = Backend()
 
-        self._loop = asyncio.get_event_loop()
-        self._loop.set_exception_handler(self._loop_exception_handler)
-
         Thread(target=self._start_asyncio_loop).start()
 
 

My version of Mirage is git version from Monday, with HEAD at 8b8829a.

@mirukana
Copy link
Owner

You're right, I didn't even notice the import Backend's position until now.
As noted by the FIXME comment at the bottom of qml_bridge.py, it seems like the thread behavior is inconsistent between different versions of python. Even stranger, I've upgraded to Python 3.8 recently and I get that problem with signals but not the one you're talking about.

In any case, if your issue #35 is fixed, is everything working with your patch? Will you make a PR, or should I just add the changes myself?

DataBeaver added a commit to DataBeaver/mirage that referenced this issue May 15, 2020
Depending on Python version the file may be imported in a thread and
asyncio only implicitly creates an event loop in the main thread of the
process.  Backend does things which need asyncio so we must ensure an
event loop exists before it is imported.

Fixes mirukana#15
@DataBeaver
Copy link
Contributor

I haven't tried any advanced features yet but now that I got #35 fixed I can at least get a working UI and view channels.

@zacharytyhacz
Copy link

I just updated my arch linux, and mirage just broke with this exact error message. What broke?

@zacharytyhacz
Copy link

Here is full log from starting mirage with the command $ mirage

~ 11:04:06 | Got library name:  "/usr/lib/qt/qml/io/thp/pyotherside/libpyo
~ 11:04:07 | "PyOtherSide error: Traceback (most recent call last):\n\n  File \"qrc:/src/backend/qml_bridge.py\", line 176, in <module>\n    BRIDGE = QMLBridge()\n\n  File \"qrc:/src/backend/qml_bridge.py\", line 53, in __init__\n    from .backend import Backend\n\n  File \"qrc:/src/backend/backend.py\", line 17, in <module>\n    from .matrix_client import MatrixClient\n\n  File \"qrc:/src/backend/matrix_client.py\", line 42, in <module>\n    from .html_markdown import HTML_PROCESSOR as HTML\n\n  File \"qrc:/src/backend/html_markdown.py\", line 9, in <module>\n    import html_sanitizer.sanitizer as sanitizer\n\nModuleNotFoundError: No module named 'html_sanitizer'\n"
! 11:04:07 | Unhandled PyOtherSide error: Cannot import module: backend.qml_bridge (Traceback (most recent call last):

  File "qrc:/src/backend/qml_bridge.py", line 176, in <module>
    BRIDGE = QMLBridge()

  File "qrc:/src/backend/qml_bridge.py", line 53, in __init__
    from .backend import Backend

  File "qrc:/src/backend/backend.py", line 17, in <module>
    from .matrix_client import MatrixClient

  File "qrc:/src/backend/matrix_client.py", line 42, in <module>
    from .html_markdown import HTML_PROCESSOR as HTML

  File "qrc:/src/backend/html_markdown.py", line 9, in <module>
    import html_sanitizer.sanitizer as sanitizer

ModuleNotFoundError: No module named 'html_sanitizer'
)
~ 11:04:07 | "PyOtherSide error: Traceback (most recent call last):\n\n  File \"<string>\", line 1, in <module>\n\nNameError: name 'BRIDGE' is not defined\n"
! 11:04:07 | Unhandled PyOtherSide error: Function not found: 'BRIDGE.call_backend_coro' (Traceback (most recent call last):

  File "<string>", line 1, in <module>

NameError: name 'BRIDGE' is not defined
)

I am on arch linux, and I guess an update with python somewhere changed some python sym links ( weird python version sym linking )

I reinstalled python2 and python2-pip ( not entirely sure if this did anything )
and then I did: $ python3 -m pip install html_sanitizer and now it is working. I am not sure what happened, but I think it had something to do with pointing to the wrong python version due to my messed up python version sym linking

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants