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
onConnecting implementation #1170
onConnecting implementation #1170
Conversation
ef21816
to
6dd5889
Compare
had a quick look: rgd the new type classes |
Okay, I was just looking at the asyncio and Twisted "transport" interfaces and it looked like they always provide Looks like Examining how we used this currently/before, Put another way, if we want to use |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code and tests look great! For IP based transports.
Which is my main worry: eg in Crossbar.io, we depend on UDS at the very least. Also we support Tor. etc. The change goes deep .. and I am worried it breaks or doesn't fit the non-IP transport we support.
autobahn/websocket/types.py
Outdated
# is_secure | ||
# peer_certificate # getPeerCertificate(), .get_extra_info('peercert') | ||
|
||
def __init__(self, peer, host): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to my above comment: what about UDS, pipes, serial, ..?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe they all return "something" on their respective platforms (i.e. ITransport
in Twisted has getHost()
and it returns an IAddress
which is .. basically "transport specific" (e.g. TCPAddress or UNIXAddress, etc). That said, I'll double-check pipes though.
not sure if that is of use, but we have 2 helpers:
|
Ahhh, interesting. I wonder if it's better to use those (and then |
yeah, that would be better IMO. we can have only one item: we also need this https://github.com/crossbario/autobahn-python/blob/master/autobahn/twisted/util.py#L94 this is the channel ID over the underlying TLS (when the transport is running TLS) I don't know how to get it on asyncio also, looking at
|
Okay, so convert |
How about this?
and
|
Sounds good. Drop |
Yeah, this looks all good for merge from my side now! Awesome. Hope it'll do for JP too;) So if don't want anything else to push on this PR from your side, please merge |
@exarkun do you see anything missing as far as the use-case for Tahoe-LAFS? (It has |
I added some documentation, a changelog entry, and put the |
going to merge it now, as I'd like to run it with ongoing development of crossbar/crossbarfx - to see if there is any unexpected fallout. should @exarkun have any itches with how this now is landed, we can do that via another PR if necessary .. |
self.port = port if port is not None else 80 | ||
self.resource = resource if resource is not None else "/" | ||
# optional | ||
self.headers = headers if headers else dict() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Kind of an anti-pattern. If headers
is an empty dict then this sets self.headers
to a different empty dict. It doesn't really matter for simple, straightforward code but it creates quite a surprise for nasty code that mutates that dict later on.
I'd suggest preserving identity:
self.headers = headers if headers is not None else dict()
And likewise for protocols
below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah, right! fwiw, the classes in "types" were envisioned as pure value holding classes - but the code as it stands is neither nor. if we'd go with "pure value types", I guess we should (deep)copy everything coming in via ctors. lets see @meejah 's opinion ..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can definitely do what @exarkun suggests (which I agree is a good idea). At some point I had some "XXX" comments about this; we can "slow everything down" by deep-copying or make it "up to the caller" to make sure they're not mutating (or, only mutating in a way that makes sense?). We should definitely do the is not None
thing ... I'm not so sure about deep-copying everything.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, so no deep copy, and preserve identity for dict: +1
while discussing this, why is dict()
better than {}
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer dict()
to avoid confusion with set()
s. A dict with one item: {"foo": "bar"}
a set with two items: {"foo", "bar"}
...you can't make an empty set with {
and }
AFAIK, but ....
used for this connection. If you wish to use the default | ||
behavior, `None` may be returned (this is the default). | ||
""" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are all non-subclassing IWebSocketChannel
implementations broken now, because they lack this method? Or is the only supported use through subclassing the ABC?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, people that implemented their own sub-classing stuff have broken classes now until they add the new callback (which is strictly expected by the calling library code). not sure if anyone has done that (wrote own classes for channel). adding dynamic attribute checking to work around that .. not sure if it is worth.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, but also the only way to "implement" an ABC is by subclassing it, isn't it? So then they'll get this empty method (which returns None
and thus "asks for defaults"). I should double-check that, but I'm fairly certain that's how ABCs work...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hrm, I think I'm wrong here ... "A class containing at least one method declared with this decorator that hasn't been overridden yet cannot be instantiated. Such methods may be called from the overriding method in the subclass (using super or direct invocation)."
That's from PEP3119. So, I think what that means is that yes, anyone who created their own classes from scratch and declared the IWebSocketChannel
"interface" via subclassing will now be broken (because they haven't implemented onConnecting
). A quick test in the repl confirms this -- you'll get TypeError: Can't instantiate abstract class Foo with abstract methods onClose, onConnect, onConnecting, onMessage, onOpen, onPing, onPong, sendClose, sendMessage, sendPing, sendPong
.
As per latest discussion in #1158