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

AttributeError: type object 'GreenSocket' has no attribute 'sendmsg' #3015

Closed
maldororxul opened this issue Jun 10, 2024 · 4 comments
Closed

Comments

@maldororxul
Copy link

I'm trying to work with openai package that uses trio on Flask app hosted on Heroku.

First it failed with 'epoll issue': #2848
I tired to fix it with monkey_patch, but got a new issue:

AttributeError: type object 'GreenSocket' has no attribute 'sendmsg'

My entry point with patch:

import eventlet
import sys
from types import ModuleType

# Apply eventlet monkey patching
eventlet.monkey_patch()

def monkey_patch_trio():
    try:
        import select
        if not hasattr(select, 'epoll'):
            class FakeEpoll:
                def __init__(self, *args, **kwargs):
                    raise NotImplementedError("epoll is not supported on this platform")

            fake_select_module = ModuleType("select")
            fake_select_module.epoll = FakeEpoll
            sys.modules["select"] = fake_select_module

    except ImportError:
        pass

monkey_patch_trio()

# Import the rest of the application after monkey patching and Flask App creating

Dependencies:

trio==0.25.1
trio-websocket==0.10.3
openai==1.30.5
eventlet==0.30.2

Error logs:

2024-06-10T13:16:50.217688+00:00 app[web.1]: Traceback (most recent call last):
2024-06-10T13:16:50.217689+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/flask/app.py", line 2190, in wsgi_app
2024-06-10T13:16:50.217689+00:00 app[web.1]:     response = self.full_dispatch_request()
2024-06-10T13:16:50.217690+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/flask/app.py", line 1486, in full_dispatch_request
2024-06-10T13:16:50.217690+00:00 app[web.1]:     rv = self.handle_user_exception(e)
2024-06-10T13:16:50.217691+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/flask_cors/extension.py", line 176, in wrapped_function
2024-06-10T13:16:50.217691+00:00 app[web.1]:     return cors_after_request(app.make_response(f(*args, **kwargs)))
2024-06-10T13:16:50.217691+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/flask/app.py", line 1484, in full_dispatch_request
2024-06-10T13:16:50.217692+00:00 app[web.1]:     rv = self.dispatch_request()
2024-06-10T13:16:50.217692+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/flask/app.py", line 1469, in dispatch_request
2024-06-10T13:16:50.217693+00:00 app[web.1]:     return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
2024-06-10T13:16:50.217693+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/flask_login/utils.py", line 290, in decorated_view
2024-06-10T13:16:50.217693+00:00 app[web.1]:     return current_app.ensure_sync(func)(*args, **kwargs)
2024-06-10T13:16:50.217694+00:00 app[web.1]:   File "/app/app/main/routes/calls_recognition.py", line 14, in add_calls_to_queue
2024-06-10T13:16:50.217695+00:00 app[web.1]:     CallsRecognitionManager(branch='sm').add_calls_from_amo(_filter={'contact_id': request.args.get('contact_id')})
2024-06-10T13:16:50.217695+00:00 app[web.1]:   File "/app/app/calls_recognition/manager.py", line 24, in __init__
2024-06-10T13:16:50.217695+00:00 app[web.1]:     self.calls_data_client = CallsDataClient(schema=branch)
2024-06-10T13:16:50.217695+00:00 app[web.1]:   File "/app/app/calls_recognition/data_client.py", line 45, in __init__
2024-06-10T13:16:50.217695+00:00 app[web.1]:     self.gpt_processor = GPTProcessor()
2024-06-10T13:16:50.217695+00:00 app[web.1]:   File "/app/app/calls_recognition/gpt_processor.py", line 11, in __init__

Here starts the problem:

2024-06-10T13:16:50.217696+00:00 app[web.1]:     from openai import OpenAI
2024-06-10T13:16:50.217696+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/openai/__init__.py", line 8, in <module>
2024-06-10T13:16:50.217697+00:00 app[web.1]:     from . import types
2024-06-10T13:16:50.217697+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/openai/types/__init__.py", line 5, in <module>
2024-06-10T13:16:50.217697+00:00 app[web.1]:     from .batch import Batch as Batch
2024-06-10T13:16:50.217697+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/openai/types/batch.py", line 7, in <module>
2024-06-10T13:16:50.217697+00:00 app[web.1]:     from .._models import BaseModel
2024-06-10T13:16:50.217697+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/openai/_models.py", line 24, in <module>
2024-06-10T13:16:50.217697+00:00 app[web.1]:     from ._types import (
2024-06-10T13:16:50.217698+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/openai/_types.py", line 21, in <module>
2024-06-10T13:16:50.217698+00:00 app[web.1]:     import httpx
2024-06-10T13:16:50.217698+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/httpx/__init__.py", line 2, in <module>
2024-06-10T13:16:50.217698+00:00 app[web.1]:     from ._api import delete, get, head, options, patch, post, put, request, stream
2024-06-10T13:16:50.217698+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/httpx/_api.py", line 4, in <module>
2024-06-10T13:16:50.217699+00:00 app[web.1]:     from ._client import Client
2024-06-10T13:16:50.217699+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/httpx/_client.py", line 30, in <module>
2024-06-10T13:16:50.217699+00:00 app[web.1]:     from ._transports.default import AsyncHTTPTransport, HTTPTransport
2024-06-10T13:16:50.217699+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/httpx/_transports/default.py", line 30, in <module>
2024-06-10T13:16:50.217699+00:00 app[web.1]:     import httpcore
2024-06-10T13:16:50.217699+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/httpcore/__init__.py", line 1, in <module>
2024-06-10T13:16:50.217699+00:00 app[web.1]:     from ._api import request, stream
2024-06-10T13:16:50.217700+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/httpcore/_api.py", line 5, in <module>
2024-06-10T13:16:50.217700+00:00 app[web.1]:     from ._sync.connection_pool import ConnectionPool
2024-06-10T13:16:50.217700+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/httpcore/_sync/__init__.py", line 1, in <module>
2024-06-10T13:16:50.217700+00:00 app[web.1]:     from .connection import HTTPConnection
2024-06-10T13:16:50.217700+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/httpcore/_sync/connection.py", line 12, in <module>
2024-06-10T13:16:50.217700+00:00 app[web.1]:     from .._synchronization import Lock
2024-06-10T13:16:50.217701+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/httpcore/_synchronization.py", line 13, in <module>
2024-06-10T13:16:50.217701+00:00 app[web.1]:     import trio
2024-06-10T13:16:50.217701+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/trio/__init__.py", line 26, in <module>
2024-06-10T13:16:50.217701+00:00 app[web.1]:     from . import abc, from_thread, lowlevel, socket, to_thread
2024-06-10T13:16:50.217702+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/trio/socket.py", line 16, in <module>
2024-06-10T13:16:50.217702+00:00 app[web.1]:     from . import _socket
2024-06-10T13:16:50.217702+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/trio/_socket.py", line 526, in <module>
2024-06-10T13:16:50.217702+00:00 app[web.1]:     class SocketType:
2024-06-10T13:16:50.217702+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/trio/_socket.py", line 719, in SocketType
2024-06-10T13:16:50.217705+00:00 app[web.1]:     @_wraps(_stdlib_socket.socket.sendmsg, assigned=(), updated=())
2024-06-10T13:16:50.217705+00:00 app[web.1]: AttributeError: type object 'GreenSocket' has no attribute 'sendmsg'
@A5rocks
Copy link
Contributor

A5rocks commented Jun 10, 2024

As a quick fix you can probably import trio before monkey patching. This will cache trio with un-patched system things.

There has to be a way to fix this that isn't just a game of whack-a-mole but I don't have any ideas.

@maldororxul
Copy link
Author

maldororxul commented Jun 11, 2024

If I import trio before monkey patching it will fall with "AttributeError: module 'select' has no attribute 'epoll'".

I ended up with this to avoid both attribute errors:

def monkey_patch_trio():
    try:
        import select
        if not hasattr(select, 'epoll'):
            class FakeEpoll:
                def __init__(self, *args, **kwargs):
                    raise NotImplementedError("epoll is not supported on this platform")

            fake_select_module = ModuleType("select")
            fake_select_module.epoll = FakeEpoll
            sys.modules["select"] = fake_select_module

        # Patch GreenSocket before trio._socket is imported
        from eventlet.greenio.base import GreenSocket as EventletGreenSocket

        if not hasattr(EventletGreenSocket, 'sendmsg'):
            setattr(EventletGreenSocket, 'sendmsg', lambda *args, **kwargs: None)
        if not hasattr(EventletGreenSocket, 'recvmsg'):
            setattr(EventletGreenSocket, 'recvmsg', lambda *args, **kwargs: None)
        if not hasattr(EventletGreenSocket, 'recvmsg_into'):
            setattr(EventletGreenSocket, 'recvmsg_into', lambda *args, **kwargs: None)

        # Now import trio._socket
        import trio._socket as trio_socket
        import socket as _stdlib_socket
        from functools import wraps as _wraps

        class PatchedSocketType(trio_socket.SocketType):
            @_wraps(_stdlib_socket.socket.sendmsg, assigned=(), updated=())
            def sendmsg(self, *args, **kwargs):
                raise NotImplementedError("sendmsg is not supported on this platform")

            @_wraps(_stdlib_socket.socket.recvmsg, assigned=(), updated=())
            def recvmsg(self, *args, **kwargs):
                raise NotImplementedError("recvmsg is not supported on this platform")

            @_wraps(_stdlib_socket.socket.recvmsg_into, assigned=(), updated=())
            def recvmsg_into(self, *args, **kwargs):
                raise NotImplementedError("recvmsg_into is not supported on this platform")

        trio_socket.SocketType = PatchedSocketType

    except ImportError:
        pass

@A5rocks
Copy link
Contributor

A5rocks commented Jun 11, 2024

Sorry, I mean import trio before running eventlet.monkey_patch().

@A5rocks
Copy link
Contributor

A5rocks commented Aug 2, 2024

Ok I thought about this some more and this is totally just an eventlet bug. They claim GreenSocket is "100% api compatible with socket.socket":

https://github.com/eventlet/eventlet/blob/8bac9b2bb5ba02d42305446327a117ff51af177b/eventlet/greenio/base.py#L119-L122

@A5rocks A5rocks closed this as not planned Won't fix, can't repro, duplicate, stale Aug 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants