Skip to content

Commit

Permalink
fix: Move tests under ld_eventsource namespace
Browse files Browse the repository at this point in the history
Previous distributions of this package included two packages --
ld_eventsource and testing. This top level testing namespace can
conflict with other packages. In fact, it conflicts with our own SDK.

In general this doesn't matter, but it may if:

1. You are using a build process that warns about conflicts (see [this
   issue][1])
2. You want to install the sdist on an unsupported platform and would
   like to be able to verify the tests.

To resolve this issue, we are moving the testing folder into the
ld_eventsource package. These testing files will only be included in the
sdist format. This allows for a smaller wheel size while also allowing
for flexibility with consumers.

[1]: launchdarkly/python-server-sdk#281
  • Loading branch information
keelerm84 committed Apr 4, 2024
1 parent eb8fbd2 commit f659746
Show file tree
Hide file tree
Showing 14 changed files with 32 additions and 32 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ test: install
.PHONY: lint
lint: #! Run type analysis and linting checks
lint: install
poetry run mypy ld_eventsource testing
poetry run mypy ld_eventsource

#
# Documentation generation
Expand Down
12 changes: 6 additions & 6 deletions ld_eventsource/config/connect_strategy.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
class ConnectStrategy:
"""
An abstraction for how :class:`.SSEClient` should obtain an input stream.
The default implementation is :meth:`http()`, which makes HTTP requests with ``urllib3``.
Or, if you want to consume an input stream from some other source, you can create your own
subclass of :class:`ConnectStrategy`.
Expand All @@ -29,7 +29,7 @@ def create_client(self, logger: Logger) -> ConnectionClient:
:param logger: the logger being used by the SSEClient
"""
raise NotImplementedError("ConnectStrategy base class cannot be used by itself")

@staticmethod
def http(
url: str,
Expand Down Expand Up @@ -62,11 +62,11 @@ def connect(self, last_event_id: Optional[str]) -> ConnectionResult:
Attempts to connect to a stream. Raises an exception if unsuccessful.
:param last_event_id: the current value of :attr:`SSEClient.last_event_id`
(should be sent to the server to support resuming an interrupted stream)
(should be sent to the server to support resuming an interrupted stream)
:return: a :class:`ConnectionResult` representing the stream
"""
raise NotImplementedError("ConnectionClient base class cannot be used by itself")

def close(self):
"""
Does whatever is necessary to release resources when the SSEClient is closed.
Expand All @@ -92,7 +92,7 @@ def __init__(
):
self.__stream = stream
self.__closer = closer

@property
def stream(self) -> Iterator[bytes]:
"""
Expand Down Expand Up @@ -121,7 +121,7 @@ def __exit__(self, type, value, traceback):
class _HttpConnectStrategy(ConnectStrategy):
def __init__(self, params: _HttpConnectParams):
self.__params = params

def create_client(self, logger: Logger) -> ConnectionClient:
return _HttpConnectionClient(self.__params, logger)

Expand Down
16 changes: 8 additions & 8 deletions ld_eventsource/config/retry_delay_strategy.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

class RetryDelayStrategy:
"""Base class of strategies for computing how long to wait before retrying a connection.
The default behavior, provided by :meth:`default()`, provides customizable exponential backoff
and jitter. Applications may also create their own subclasses of RetryDelayStrategy if they
desire different behavior. It is generally a best practice to use backoff and jitter, to avoid
Expand Down Expand Up @@ -51,12 +51,12 @@ def default(
equal to the current base delay minus a pseudo-random number equal to that ratio times itself.
For instance, a jitter multiplier of 0.25 would mean that a base delay of 1000 is changed to a
value in the range [750, 1000].
:param max_delay: the maximum possible delay value, in seconds; default is 30 seconds
:param backoff_multiplier: the exponential backoff factor
:param jitter_multiplier: a fraction from 0.0 to 1.0 for how much of the delay may be
pseudo-randomly subtracted
pseudo-randomly subtracted
"""
return _DefaultRetryDelayStrategy(max_delay or 0, backoff_multiplier, jitter_multiplier or 0,
0, _ReusableRandom(time.time()))
Expand All @@ -66,7 +66,7 @@ def from_lambda(fn: Callable[[float], Tuple[float, Optional[RetryDelayStrategy]]
"""
Convenience method for creating a RetryDelayStrategy whose ``apply`` method is equivalent to
the given lambda.
The one difference is that the second return value is an ``Optional[RetryDelayStrategy]`` which
can be None to mean "no change", since the lambda cannot reference the strategy's ``self``.
"""
Expand Down Expand Up @@ -101,7 +101,7 @@ def apply(self, base_delay: float) -> Tuple[float, RetryDelayStrategy]:
# state as our previous Random before using it.
random = random.clone()
adjusted_delay -= (random.random() * self.__jitter_multiplier * adjusted_delay)

next_strategy = _DefaultRetryDelayStrategy(
self.__max_delay,
self.__backoff_multiplier,
Expand All @@ -114,7 +114,7 @@ def apply(self, base_delay: float) -> Tuple[float, RetryDelayStrategy]:
class _LambdaRetryDelayStrategy(RetryDelayStrategy):
def __init__(self, fn: Callable[[float], Tuple[float, Optional[RetryDelayStrategy]]]):
self.__fn = fn

def apply(self, base_delay: float) -> Tuple[float, RetryDelayStrategy]:
delay, maybe_next = self.__fn(base_delay)
return (delay, maybe_next or self)
Expand All @@ -123,7 +123,7 @@ class _ReusableRandom:
def __init__(self, seed: float):
self.__seed = seed
self.__random = Random(seed)

def clone(self):
state = self.__random.getstate()
ret = _ReusableRandom(self.__seed)
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion testing/helpers.py → ld_eventsource/testing/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from ld_eventsource.config import *
from ld_eventsource.errors import *

from testing.http_util import *
from ld_eventsource.testing.http_util import *

from logging import Logger
from typing import Iterable, Iterator, List, Optional
Expand Down
6 changes: 3 additions & 3 deletions testing/http_util.py → ld_eventsource/testing/http_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ def __init__(self, port, secure):
if secure:
self.server.socket = ssl.wrap_socket(
self.server.socket,
certfile='./testing/selfsigned.pem', # this is a pre-generated self-signed cert that is valid for 100 years
keyfile='./testing/selfsigned.key',
certfile='./ld_eventsource/testing/selfsigned.pem', # this is a pre-generated self-signed cert that is valid for 100 years
keyfile='./ld_eventsource/testing/selfsigned.key',
server_side=True
)
self.server.server_wrapper = self
Expand All @@ -76,7 +76,7 @@ def require_request(self):
def wait_until_request_received(self):
req = self.requests.get()
self.requests.put(req)

def should_have_requests(self, count):
if self.requests.qsize() != count:
rs = []
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from ld_eventsource.config.connect_strategy import *

from testing.helpers import *
from testing.http_util import *
from ld_eventsource.testing.helpers import *
from ld_eventsource.testing.http_util import *

import logging
from urllib3.exceptions import ProtocolError
Expand Down Expand Up @@ -87,7 +87,7 @@ def test_http_io_error():
raise Exception("expected exception, did not get one")
except ProtocolError as e:
pass

def test_auto_redirect_301():
with start_server() as server:
with make_stream() as stream:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from ld_eventsource import *
from ld_eventsource.config import *

from testing.helpers import *
from testing.http_util import *
from ld_eventsource.testing.helpers import *
from ld_eventsource.testing.http_util import *

# Tests of basic SSEClient behavior using real HTTP requests.

Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from ld_eventsource.actions import *
from ld_eventsource.config import *

from testing.helpers import *
from ld_eventsource.testing.helpers import *

import pytest

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from ld_eventsource.actions import *
from ld_eventsource.config import *

from testing.helpers import *
from ld_eventsource.testing.helpers import *


def test_retry_during_initial_connect_succeeds():
Expand Down Expand Up @@ -88,7 +88,7 @@ def test_all_iterator_continues_after_retry():

item4 = next(all)
assert isinstance(item4, Start)

item5 = next(all)
assert isinstance(item5, Event)
assert item5.data == 'data2'
Expand Down Expand Up @@ -125,10 +125,10 @@ def test_can_interrupt_and_restart_stream():

item3 = next(all)
assert isinstance(item3, Fault)

item4 = next(all)
assert isinstance(item4, Start)

item5 = next(all)
assert isinstance(item5, Event)
assert item5.data == 'data3'
6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ classifiers = [
"Topic :: Software Development",
"Topic :: Software Development :: Libraries",
]
packages = [
{ include = "ld_eventsource" },
{ include = "testing" },
packages = [ { include = "ld_eventsource" } ]
exclude = [
{ path = "ld_eventsource/testing", format = "wheel" }
]

[tool.poetry.dependencies]
Expand Down

0 comments on commit f659746

Please sign in to comment.