-
Notifications
You must be signed in to change notification settings - Fork 19
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
Formalize endpoint running vs serving and cleanup some tests #75
Formalize endpoint running vs serving and cleanup some tests #75
Conversation
None of my pull requests on this repo run the first time I push them. Anyone else experiencing that? |
6be67bf
to
2420657
Compare
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 have a bunch of cleanup to do first...
while self.is_running: | ||
try: | ||
(item, config) = await self._receiving_queue.get() | ||
except RuntimeError as err: |
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.
TODO: this should get pulled out to it's own PR.
lahja/asyncio/endpoint.py
Outdated
|
||
def receive_message(self, message: Broadcast) -> None: | ||
self.logger.info("RECEIVING: %s", message) |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
lahja/asyncio/endpoint.py
Outdated
self._child_tasks.add(asyncio.ensure_future(self._connect_receiving_queue())) | ||
|
||
await self._receiving_loop_running.wait() | ||
self.logger.info("Endpoint %s started", self.name) |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
lahja/asyncio/endpoint.py
Outdated
if str(err) == "Event loop is closed": | ||
break | ||
raise | ||
self.logger.info("GOT %s from receiving queue", item) |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
lahja/asyncio/endpoint.py
Outdated
@@ -534,6 +527,7 @@ def is_connected_to(self, endpoint_name: str) -> bool: | |||
return endpoint_name in self._outbound_connections | |||
|
|||
def _process_item(self, item: BaseEvent, config: Optional[BroadcastConfig]) -> None: | |||
self.logger.info("PROCESSING: %s", item) |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
@@ -70,7 +82,7 @@ def serve(cls, config: ConnectionConfig) -> AsyncContextManager["BaseEndpoint"]: | |||
# server stopped | |||
|
|||
""" | |||
pass | |||
... |
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.
@carver @cburgdorf what do you think about this convention. It feels like it make abstractmethod
s more visually distinct.
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'm happy with it 👍 Although if we start using autoflake
maybe it will be moot because either one (pass
or ...
) would be stripped out.
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.
Looks like autoflake
leaves ...
in place so maybe that's an argument to use it.
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.
Interesting 👍
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.
In general, I'm:+1: but there is one thing I'd like to bring up.
Consider, that you forget to subclass from ABC
like we recently had in Trinity
In that case the @abstractmethod
is simply ignored and neither pass
nor ...
give you any safety here. The only pattern that still ends up doing the right thing in that situation is with raise
.
from abc import ABC, abstractmethod
class Foo():
@abstractmethod
def bar(self):
raise Exception("Needs to implemented in subclass")
Foo().bar()
I'm not insisting we should go back to raising errors but I wanted to bring it up as food for thought.
lahja/base.py
Outdated
event = await agen.asend(None) | ||
self.logger.info("CLOSING STREAM") |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
|
||
import pytest | ||
|
||
from lahja import AsyncioEndpoint, BaseEvent, ConnectionConfig |
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.
These tests don't really belong here and shouldn't be introduced until the reverse connection APIs go into place.
await endpoint.start_serving(own) | ||
|
||
with pytest.raises(ConnectionAttemptRejected): | ||
endpoint.connect_to_endpoints_nowait(own, own) |
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.
These felt really odd to be testing using these non-core APIs so I changed to only use connect_to_endpoint
.
I'm feeling like I want to remove the various extra connect_to_endpointXXXXX
APIs as they feel like they add clutter and are only moderately more useful.
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.
A quick scan through Trinity shows that we are still using connect_to_endpoints_nowait
but it looks like the usage could be easily dropped now. I'm on board with removing connect_to_endpoints_nowait
👍
|
||
await second_endpoint.broadcast(DummyResponse(None)) | ||
|
||
second_endpoint.stop() |
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.
Deleted this test because it didn't feel valuable after writing a few tests for Endpoint.run()
API.
lahja/asyncio/endpoint.py
Outdated
@@ -509,6 +501,7 @@ def connect_to_endpoints_nowait(self, *endpoints: ConnectionConfig) -> None: | |||
await self.connect_to_endpoint(endpoint) | |||
|
|||
async def connect_to_endpoint(self, config: ConnectionConfig) -> None: | |||
self._throw_if_already_connected(config) |
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.
This should be pulled out to a separate PR.
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.
addressed in #77 but leaving in here so tests pass.
2420657
to
34a37bd
Compare
34a37bd
to
3c98105
Compare
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.
Quite a few changes. Overall looks like a great improvement 👍
I left some comments that you might want to address but nothing big that stands out.
lahja/asyncio/endpoint.py
Outdated
@@ -593,7 +599,7 @@ def stop(self) -> None: | |||
if config is not None and config.internal: | |||
# Internal events simply bypass going through the central event bus | |||
# and are directly put into the local receiving queue instead. |
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 comment 👆 is still mentioning the "local receiving queue" that does no longer exist.
@@ -70,7 +82,7 @@ def serve(cls, config: ConnectionConfig) -> AsyncContextManager["BaseEndpoint"]: | |||
# server stopped | |||
|
|||
""" | |||
pass | |||
... |
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.
In general, I'm:+1: but there is one thing I'd like to bring up.
Consider, that you forget to subclass from ABC
like we recently had in Trinity
In that case the @abstractmethod
is simply ignored and neither pass
nor ...
give you any safety here. The only pattern that still ends up doing the right thing in that situation is with raise
.
from abc import ABC, abstractmethod
class Foo():
@abstractmethod
def bar(self):
raise Exception("Needs to implemented in subclass")
Foo().bar()
I'm not insisting we should go back to raising errors but I wanted to bring it up as food for thought.
) | ||
|
||
|
||
class Response(BaseEvent): |
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.
Why does this file declare new events instead of reusing those from helpers
?
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 helpers
events were adding mental overhead. I had to remember if they had properties/constructor arguments, deal with importing them. I've also liked using semantically meaningful names in the tests which is less apparent here, but more-so in some of the other ones I've written.
And last, I have tried to move away from imports from modules within the ./tests
namespace. They feel wrong. Nothing under ./tests
are actually proper python modules (no __init__.py
present), so I've been leaning towards relegating anything that needs to be re-used in tests to either be a fixture
or live in library.tools
somewhere.
await endpoint.start_serving(own) | ||
|
||
with pytest.raises(ConnectionAttemptRejected): | ||
endpoint.connect_to_endpoints_nowait(own, own) |
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.
A quick scan through Trinity shows that we are still using connect_to_endpoints_nowait
but it looks like the usage could be easily dropped now. I'm on board with removing connect_to_endpoints_nowait
👍
|
||
|
||
class Internal(BaseEvent): | ||
pass |
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.
Why not use DummyRequest
from helpers?
tests/core/asyncio/test_internal.py
Outdated
asyncio.ensure_future(do_wait_for(endpoint_a, got_by_endpoint_a)) | ||
will_not_finish = asyncio.ensure_future(do_wait_for(endpoint_b, got_by_endpoint_b)) | ||
# give subscriptions time to update | ||
await asyncio.sleep(0.01) |
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.
This could be written as:
await wait_until_all_connections_subscribed_to(Internal)
await asyncio.sleep(0.01) | ||
|
||
assert got_by_endpoint_a.is_set() is True | ||
assert got_by_endpoint_b.is_set() is False |
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 test got a whole lot more readable 👍
3c98105
to
336eca0
Compare
What was wrong?
This addresses a few loosely connected issues:
name
attribute on an endpoint was not reliably present.connect_to_endpoint
API for whether already connected.How was it fixed?
name
Queue
for internal events in favor of immediate processing.connect_to_endpoint
API for duplicates.Cute Animal Picture