Skip to content

Feature/wrap socket #878

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

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open

Conversation

leon1995
Copy link

@leon1995 leon1995 commented Feb 24, 2025

Changes

Fixes #845

Checklist

If this is a user-facing code change, like a bugfix or a new feature, please ensure that
you've fulfilled the following conditions (where applicable):

  • You've added tests (in tests/) added which would fail without your patch
  • You've updated the documentation (in docs/, in case of behavior changes or new
    features)
  • You've added a new changelog entry (in docs/versionhistory.rst).

If this is a trivial change, like a typo fix or a code reformatting, then you can ignore
these instructions.

Updating the changelog

If there are no entries after the last release, use **UNRELEASED** as the version.
If, say, your patch fixes issue #123, the entry should look like this:

- Fix big bad boo-boo in task groups
  (`#123 <https://github.com/agronholm/anyio/issues/123>`_; PR by @yourgithubaccount)

If there's no issue linked, just link to your pull request instead by updating the
changelog after you've created the PR.

@leon1995
Copy link
Author

I dont know why mypy is complaining here because I just copied the call from the connted_tcp method (and swapped the parameters for the socket)

)
return ConnectedUDPSocket(transport, protocol)
elif raw_socket.type == socket.SocketKind.SOCK_STREAM:
transport, protocol = cast( # type: ignore[assignment] # mypy is not able to properly infer the type on unix
Copy link
Collaborator

@graingert graingert Mar 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is because tranport and protocol are already declared on line 2654

will it work if you use unpacking directly into the constructor?

    SocketStream(
        *(
            await get_running_loop().create_connection(
                StreamProtocol,
                sock=raw_socket,
            )
        )
    )

or you could use different variable names, eg:dgram_transport, dgram_protocol = ... and stream_transport, stream_protocol = ...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -1526,6 +1530,65 @@ async def test_send_after_close(self, family: AnyIPAddressFamily) -> None:
await udp.send(b"foo")


@pytest.mark.network
@pytest.mark.usefixtures("check_asyncio_bug")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

apparently this is fixed in python/cpython#83329

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah it's not actually fixed, I tried it out

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but the tests pass, so should I add it again or not?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah probably because you're not sending any data

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That doesn't explain why all the tests pass.

@agronholm
Copy link
Owner

Before you go any further, I must point out that the notion of "client" UDP socket being always connected is fundamentally wrong, and the same function should not be used to wrap either a TCP socket or a UDP socket either. The notion of "connection" for a UDP socket just means that it has a default target address. An unconnected UDP socket could just as well be a client or a server socket.

@leon1995
Copy link
Author

Before you go any further, I must point out that the notion of "client" UDP socket being always connected is fundamentally wrong, and the same function should not be used to wrap either a TCP socket or a UDP socket either. The notion of "connection" for a UDP socket just means that it has a default target address. An unconnected UDP socket could just as well be a client or a server socket.

What do you suggest then? I picked up the suggested interface from #845

@agronholm
Copy link
Owner

Before you go any further, I must point out that the notion of "client" UDP socket being always connected is fundamentally wrong, and the same function should not be used to wrap either a TCP socket or a UDP socket either. The notion of "connection" for a UDP socket just means that it has a default target address. An unconnected UDP socket could just as well be a client or a server socket.

What do you suggest then? I picked up the suggested interface from #845

Well, that suggestion was also wrong then. I have to think about this for a little bit. Perhaps class methods in the respective socket stream/listener classes would do it? At any rate, let's reach a consensus before proceeding any further.

@leon1995
Copy link
Author

leon1995 commented Mar 20, 2025

Before you go any further, I must point out that the notion of "client" UDP socket being always connected is fundamentally wrong, and the same function should not be used to wrap either a TCP socket or a UDP socket either. The notion of "connection" for a UDP socket just means that it has a default target address. An unconnected UDP socket could just as well be a client or a server socket.

What do you suggest then? I picked up the suggested interface from #845

Well, that suggestion was also wrong then. I have to think about this for a little bit. Perhaps class methods in the respective socket stream/listener classes would do it? At any rate, let's reach a consensus before proceeding any further.

that might be a good idea. something like

class SocketStream(ByteStream, _SocketProvider):
    """
    Transports bytes over a socket.

    Supports all relevant extra attributes from :class:`~SocketAttribute`.
    """
    @classmethod
    @abstractmethod
    def from_socket(cls, raw_socket: socket.socket) -> SocketStream: ...

What do you think? Or should we include a hint to stdlib sockets like

    @classmethod
    @abstractmethod
    def from_stdlib_socket(cls, stdlib_socket: socket.socket) -> SocketStream: ...

?

@agronholm
Copy link
Owner

We can't add new abstract methods to public classes as that would break compatibility for anyone implementing their own SocketStream subclass.

@agronholm
Copy link
Owner

I'll have to think about this some more when I get the time and I'm not working on my day job.

@leon1995
Copy link
Author

I'll have to think about this some more when I get the time and I'm not working on my day job.

Have you come to any conclusion yet?

@agronholm
Copy link
Owner

Not yet, sorry.

@agronholm
Copy link
Owner

I'll try to work on this issue this weekend.

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

Successfully merging this pull request may close these issues.

add the ability to wrap stdlib sockets
3 participants