Skip to content

Commit

Permalink
Hotfix (#166)
Browse files Browse the repository at this point in the history
* Added README.rst to poetry version bump

* Refactored yield -> return in all fixtures that makes sense

* Cleanup

* More code documentation
  • Loading branch information
Nusnus authored Jan 14, 2024
1 parent d5b614e commit cabe599
Show file tree
Hide file tree
Showing 19 changed files with 78 additions and 89 deletions.
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

|build-status| |coverage| |license| |semgrep| |pyversion| |pyimp| |ocbackerbadge| |ocsponsorbadge|

:Version: 1.0.0 (TBD)
:Version: 1.0.0a12
:Web: https://pytest-celery.readthedocs.io/en/latest/
:Download: https://pypi.org/project/pytest-celery/
:Source: https://github.com/celery/pytest-celery/
Expand Down
3 changes: 3 additions & 0 deletions examples/myworker/tests/test_myworker.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@ def celery_worker_cluster(
celery_worker: CeleryTestWorker,
myworker_worker: CeleryTestWorker,
) -> CeleryWorkerCluster:
"""Add myworker worker to the workers cluster alongside the parametrize
plugin worker."""
cluster = CeleryWorkerCluster(celery_worker, myworker_worker) # type: ignore
yield cluster
cluster.teardown()


def test_ping(celery_setup: CeleryTestSetup):
"""Test ping task for each worker node."""
worker: CeleryTestWorker
for worker in celery_setup.worker_cluster:
sig: Signature = ping.s()
Expand Down
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ version = "1.0.0a12"
search = '__version__ = "{current_version}"'
replace = '__version__ = "{new_version}"'

[tool.poetry_bumpversion.file."README.rst"]
search = ':Version: {current_version}'
replace = ':Version: {new_version}'

[tool.poetry.dependencies]
python = ">= 3.8,<4.0"
celery = { version = "^5", extras = ["redis", "pymemcache"] }
Expand Down
22 changes: 6 additions & 16 deletions src/pytest_celery/api/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@

from pytest_celery.api.base import CeleryTestCluster
from pytest_celery.api.base import CeleryTestNode
from pytest_celery.api.container import CeleryTestContainer
from pytest_celery.defaults import DEFAULT_WORKER_ENV


class CeleryTestBackend(CeleryTestNode):
"""CeleryTestBackend is specialized node type for handling celery backends
nodes. It is used to encapsulate a backend instance.
"""This is specialized node type for handling celery backends nodes. It is
used to encapsulate a backend instance.
Responsibility Scope:
Handling backend specific requirements and configuration.
Expand All @@ -22,6 +21,8 @@ def default_config(cls) -> dict:
}

def restart(self, reload_container: bool = True, force: bool = False) -> None:
"""Override restart method to update the app result backend with new
container values."""
super().restart(reload_container, force)
if self.app:
self.app.conf.update(
Expand All @@ -30,24 +31,13 @@ def restart(self, reload_container: bool = True, force: bool = False) -> None:


class CeleryBackendCluster(CeleryTestCluster):
"""CeleryBackendCluster is a specialized cluster type for handling celery
backends. It is used to define which backend instances are available for
the test.
"""This is a specialized cluster type for handling celery backends. It is
used to define which backend instances are available for the test.
Responsibility Scope:
Provude useful methods for managing a cluster of celery backends.
"""

def __init__(self, *backends: tuple[CeleryTestBackend | CeleryTestContainer]) -> None:
super().__init__(*backends)

def _set_nodes(
self,
*nodes: tuple[CeleryTestNode | CeleryTestContainer],
node_cls: type[CeleryTestNode] = CeleryTestBackend,
) -> tuple[CeleryTestNode]:
return super()._set_nodes(*nodes, node_cls=node_cls)

@classmethod
def default_config(cls) -> dict:
return {
Expand Down
26 changes: 16 additions & 10 deletions src/pytest_celery/api/base.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from __future__ import annotations

from abc import abstractmethod
from typing import Any
from typing import Iterator

import pytest_docker_tools
Expand All @@ -14,9 +13,9 @@


class CeleryTestNode:
"""CeleryTestNode is the logical representation of a container instance. It
is used to provide a common interface for interacting with the container
regardless of the underlying implementation.
"""This is the logical representation of a container instance. It is used
to provide a common interface for interacting with the container regardless
of the underlying implementation.
Responsibility Scope:
The node's responsibility is to wrap the container and provide
Expand Down Expand Up @@ -44,6 +43,8 @@ def app(self) -> Celery:
return self._app

def __eq__(self, other: object) -> bool:
"""Two nodes are equal if they have the same container and Celery
app."""
if isinstance(other, CeleryTestNode):
return all(
(
Expand Down Expand Up @@ -152,8 +153,8 @@ def assert_log_does_not_exist(self, log: str, message: str = "", timeout: int =


class CeleryTestCluster:
"""CeleryTestCluster is a collection of CeleryTestNodes. It is used to
collect the test nodes into a single object for easier management.
"""This is a collection of CeleryTestNodes. It is used to collect the test
nodes into a single object for easier management.
Responsibility Scope:
The cluster's responsibility is to define which nodes will be used for
Expand Down Expand Up @@ -194,19 +195,24 @@ def nodes(self, nodes: tuple[CeleryTestNode | CeleryTestContainer]) -> None:
self._nodes = self._set_nodes(*nodes) # type: ignore

def __iter__(self) -> Iterator[CeleryTestNode]:
"""Iterate over the nodes of the cluster."""
return iter(self.nodes)

def __getitem__(self, index: Any) -> CeleryTestNode:
def __getitem__(self, index: int) -> CeleryTestNode:
"""Get a node from the cluster by index."""
return self.nodes[index]

def __len__(self) -> int:
"""Get the number of nodes in the cluster."""
return len(self.nodes)

def __eq__(self, other: object) -> bool:
"""Two clusters are equal if they have the same nodes."""
if isinstance(other, CeleryTestCluster):
for node in self:
if node not in other:
return False
if len(self) == len(other):
for node in self:
if node not in other:
return False
return False

@classmethod
Expand Down
22 changes: 6 additions & 16 deletions src/pytest_celery/api/broker.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@

from pytest_celery.api.base import CeleryTestCluster
from pytest_celery.api.base import CeleryTestNode
from pytest_celery.api.container import CeleryTestContainer
from pytest_celery.defaults import DEFAULT_WORKER_ENV


class CeleryTestBroker(CeleryTestNode):
"""CeleryTestBroker is specialized node type for handling celery brokers
nodes. It is used to encapsulate a broker instance.
"""This is specialized node type for handling celery brokers nodes. It is
used to encapsulate a broker instance.
Responsibility Scope:
Handling broker specific requirements and configuration.
Expand All @@ -22,6 +21,8 @@ def default_config(cls) -> dict:
}

def restart(self, reload_container: bool = True, force: bool = False) -> None:
"""Override restart method to update the app broker url with new
container values."""
super().restart(reload_container, force)
if self.app:
self.app.conf.update(
Expand All @@ -30,24 +31,13 @@ def restart(self, reload_container: bool = True, force: bool = False) -> None:


class CeleryBrokerCluster(CeleryTestCluster):
"""CeleryBrokerCluster is a specialized cluster type for handling celery
brokers. It is used to define which broker instances are available for the
test.
"""This is a specialized cluster type for handling celery brokers. It is
used to define which broker instances are available for the test.
Responsibility Scope:
Provude useful methods for managing a cluster of celery brokers.
"""

def __init__(self, *brokers: tuple[CeleryTestBroker | CeleryTestContainer]) -> None:
super().__init__(*brokers)

def _set_nodes(
self,
*nodes: tuple[CeleryTestNode | CeleryTestContainer],
node_cls: type[CeleryTestNode] = CeleryTestBroker,
) -> tuple[CeleryTestNode]:
return super()._set_nodes(*nodes, node_cls=node_cls)

@classmethod
def default_config(cls) -> dict:
return {
Expand Down
2 changes: 2 additions & 0 deletions src/pytest_celery/api/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ def __init__(
self.ping = ping

def __len__(self) -> int:
"""The total number of nodes in the setup."""
return len(self._worker_cluster) + len(self._broker_cluster) + len(self._backend_cluster)

@property
Expand Down Expand Up @@ -88,6 +89,7 @@ def worker(self) -> CeleryTestWorker:

@classmethod
def name(cls) -> str:
"""The name of the setup."""
# TODO: Possibly not needed/required refactoring
return DEFAULT_WORKER_APP_NAME

Expand Down
19 changes: 4 additions & 15 deletions src/pytest_celery/api/worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@


class CeleryTestWorker(CeleryTestNode):
"""CeleryTestWorker is specialized node type for handling celery worker
nodes. It is used to encapsulate a worker instance.
"""This is specialized node type for handling celery worker nodes. It is
used to encapsulate a worker instance.
Responsibility Scope:
Managing a celery worker.
Expand Down Expand Up @@ -98,24 +98,13 @@ def get_running_processes_info(


class CeleryWorkerCluster(CeleryTestCluster):
"""CeleryWorkerCluster is a specialized cluster type for handling celery
workers. It is used to define which worker instances are available for the
test.
"""This is a specialized cluster type for handling celery workers. It is
used to define which worker instances are available for the test.
Responsibility Scope:
Provude useful methods for managing a cluster of celery workers.
"""

def __init__(self, *workers: tuple[CeleryTestWorker | CeleryTestContainer]) -> None:
super().__init__(*workers)

def _set_nodes(
self,
*nodes: tuple[CeleryTestNode | CeleryTestContainer],
node_cls: type[CeleryTestNode] = CeleryTestWorker,
) -> tuple[CeleryTestNode]:
return super()._set_nodes(*nodes, node_cls=node_cls)

@property
def versions(self) -> set[str]:
"""Celery versions of all workers in this cluster."""
Expand Down
6 changes: 3 additions & 3 deletions src/pytest_celery/fixtures/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def celery_setup( # type: ignore
@pytest.fixture
def celery_setup_name(celery_setup_cls: type[CeleryTestSetup]) -> str: # type: ignore
"""Fixture interface to the API."""
yield celery_setup_cls.name()
return celery_setup_cls.name()


@pytest.fixture
Expand All @@ -64,7 +64,7 @@ def celery_setup_config(
celery_worker_cluster_config: dict,
) -> dict:
"""Fixture interface to the API."""
yield celery_setup_cls.config(
return celery_setup_cls.config(
celery_worker_cluster_config=celery_worker_cluster_config,
)

Expand All @@ -76,7 +76,7 @@ def celery_setup_app(
celery_setup_name: str,
) -> Celery:
"""Fixture interface to the API."""
yield celery_setup_cls.create_setup_app(
return celery_setup_cls.create_setup_app(
celery_setup_config=celery_setup_config,
celery_setup_app_name=celery_setup_name,
)
6 changes: 3 additions & 3 deletions src/pytest_celery/vendors/memcached/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@ def default_memcached_backend_cls() -> type[MemcachedContainer]:

@pytest.fixture
def default_memcached_backend_env(default_memcached_backend_cls: type[MemcachedContainer]) -> dict:
yield default_memcached_backend_cls.env()
return default_memcached_backend_cls.env()


@pytest.fixture
def default_memcached_backend_image(default_memcached_backend_cls: type[MemcachedContainer]) -> str:
yield default_memcached_backend_cls.image()
return default_memcached_backend_cls.image()


@pytest.fixture
def default_memcached_backend_ports(default_memcached_backend_cls: type[MemcachedContainer]) -> dict:
yield default_memcached_backend_cls.ports()
return default_memcached_backend_cls.ports()
6 changes: 3 additions & 3 deletions src/pytest_celery/vendors/rabbitmq/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@ def default_rabbitmq_broker_cls() -> type[RabbitMQContainer]:

@pytest.fixture
def default_rabbitmq_broker_env(default_rabbitmq_broker_cls: type[RabbitMQContainer]) -> dict:
yield default_rabbitmq_broker_cls.env()
return default_rabbitmq_broker_cls.env()


@pytest.fixture
def default_rabbitmq_broker_image(default_rabbitmq_broker_cls: type[RabbitMQContainer]) -> str:
yield default_rabbitmq_broker_cls.image()
return default_rabbitmq_broker_cls.image()


@pytest.fixture
def default_rabbitmq_broker_ports(default_rabbitmq_broker_cls: type[RabbitMQContainer]) -> dict:
yield default_rabbitmq_broker_cls.ports()
return default_rabbitmq_broker_cls.ports()
2 changes: 1 addition & 1 deletion src/pytest_celery/vendors/redis/backend/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ def teardown(self) -> None:
# and the Redis container. The AsyncResult object tries
# to release the connection but the Redis container has already
# exited. This causes a warning to be logged. To avoid this
# warning we force a garbage collection here.
# warning to our best effort we force a garbage collection here.
gc.collect(1)
super().teardown()
6 changes: 3 additions & 3 deletions src/pytest_celery/vendors/redis/backend/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@ def default_redis_backend_cls() -> type[RedisContainer]:

@pytest.fixture
def default_redis_backend_env(default_redis_backend_cls: type[RedisContainer]) -> dict:
yield default_redis_backend_cls.env()
return default_redis_backend_cls.env()


@pytest.fixture
def default_redis_backend_image(default_redis_backend_cls: type[RedisContainer]) -> str:
yield default_redis_backend_cls.image()
return default_redis_backend_cls.image()


@pytest.fixture
def default_redis_backend_ports(default_redis_backend_cls: type[RedisContainer]) -> dict:
yield default_redis_backend_cls.ports()
return default_redis_backend_cls.ports()
6 changes: 3 additions & 3 deletions src/pytest_celery/vendors/redis/broker/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@ def default_redis_broker_cls() -> type[RedisContainer]:

@pytest.fixture
def default_redis_broker_env(default_redis_broker_cls: type[RedisContainer]) -> dict:
yield default_redis_broker_cls.env()
return default_redis_broker_cls.env()


@pytest.fixture
def default_redis_broker_image(default_redis_broker_cls: type[RedisContainer]) -> str:
yield default_redis_broker_cls.image()
return default_redis_broker_cls.image()


@pytest.fixture
def default_redis_broker_ports(default_redis_broker_cls: type[RedisContainer]) -> dict:
yield default_redis_broker_cls.ports()
return default_redis_broker_cls.ports()
Loading

0 comments on commit cabe599

Please sign in to comment.