Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/pr_codeql.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
name: "CodeQL"

on:
push:
branches:
- main
paths:
- faststream/**
pull_request:
types:
- opened
Expand Down
6 changes: 3 additions & 3 deletions faststream/_internal/context/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,11 @@ def scope(self, key: str, value: Any) -> Iterator[None]:
key: The key of the local variable
value: The value to set the local variable to

Yields:
None

Returns:
An iterator that yields None

Yields:
None
"""
token = self.set_local(key, value)
try:
Expand Down
21 changes: 19 additions & 2 deletions faststream/rabbit/schemas/channel.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from dataclasses import dataclass


@dataclass
@dataclass(eq=False)
class Channel:
"""Channel class that represents a RabbitMQ channel."""

Expand All @@ -28,5 +28,22 @@ class Channel:
"""raise an :class:`aio_pika.exceptions.DeliveryError`
when mandatory message will be returned"""

def __eq__(self, other: object) -> bool:
if not isinstance(other, Channel):
return NotImplemented
return (
self.prefetch_count == other.prefetch_count
and self.global_qos == other.global_qos
and self.channel_number == other.channel_number
and self.publisher_confirms == other.publisher_confirms
and self.on_return_raises == other.on_return_raises
)

def __hash__(self) -> int:
return id(self)
return hash((
self.prefetch_count,
self.global_qos,
self.channel_number,
self.publisher_confirms,
self.on_return_raises,
))
32 changes: 26 additions & 6 deletions faststream/rabbit/schemas/exchange.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,35 @@ def __repr__(self) -> str:

return f"{self.__class__.__name__}({self.name}, type={self.type}, routing_key='{self.routing()}'{body})"

def __eq__(self, value: object, /) -> bool:
if not isinstance(value, RabbitExchange):
return NotImplemented

return (
self.name == value.name
and self.type == value.type
and self.routing_key == value.routing_key
and self.durable == value.durable
and self.auto_delete == value.auto_delete
and self.arguments == value.arguments
)

def __hash__(self) -> int:
"""Supports hash to store real objects in declarer."""
return sum(

def _hash_dict(d: Any) -> Any:
if isinstance(d, dict):
return frozenset((k, _hash_dict(v)) for k, v in d.items())
return d

return hash(
(
hash(self.name),
hash(self.type),
hash(self.routing_key),
int(self.durable),
int(self.auto_delete),
self.name,
self.type,
self.routing_key,
self.durable,
self.auto_delete,
_hash_dict(self.arguments or {}),
),
)

Expand Down
29 changes: 24 additions & 5 deletions faststream/rabbit/schemas/queue.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,33 @@ def __repr__(self) -> str:

return f"{self.__class__.__name__}({self.name}{body})"

def __eq__(self, value: object, /) -> bool:
if not isinstance(value, RabbitQueue):
return NotImplemented

return (
self.name == value.name
and self.durable == value.durable
and self.exclusive == value.exclusive
and self.auto_delete == value.auto_delete
and self.arguments == value.arguments
)

def __hash__(self) -> int:
"""Supports hash to store real objects in declarer."""
return sum(

def _hash_dict(d: Any) -> Any:
if isinstance(d, dict):
return frozenset((k, _hash_dict(v)) for k, v in d.items())
return d

return hash(
(
hash(self.name),
int(self.durable),
int(self.exclusive),
int(self.auto_delete),
self.name,
self.durable,
self.exclusive,
self.auto_delete,
_hash_dict(self.arguments or {}),
),
)

Expand Down
4 changes: 3 additions & 1 deletion faststream/rabbit/testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,9 @@ def _is_handler_matches(
headers = headers or {}
exchange = RabbitExchange.validate(exchange)

if handler.exchange != exchange:
if (handler.exchange.name if handler.exchange else None) != (
exchange.name if exchange else None
):
return False

if handler.exchange is None or handler.exchange.type == ExchangeType.DIRECT:
Expand Down
49 changes: 48 additions & 1 deletion tests/brokers/rabbit/test_schemas.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from faststream.rabbit import RabbitQueue
from faststream.rabbit import Channel, RabbitExchange, RabbitQueue


@pytest.mark.rabbit()
Expand All @@ -23,3 +23,50 @@ def test_different_queue_routing_key() -> None:
})
== 1
)


@pytest.mark.rabbit()
def test_different_queue_params() -> None:
assert (
len({
RabbitQueue("test", durable=True): 0,
RabbitQueue("test", durable=False): 1,
})
== 2
)


@pytest.mark.rabbit()
def test_exchange_equality() -> None:
assert (
len({
RabbitExchange("test", durable=True): 0,
RabbitExchange("test", durable=True): 1,
})
== 1
)
assert (
len({
RabbitExchange("test", durable=True): 0,
RabbitExchange("test", durable=False): 1,
})
== 2
)


@pytest.mark.rabbit()
def test_channel_equality() -> None:
assert (
len({
Channel(prefetch_count=10): 0,
Channel(prefetch_count=10): 1,
})
== 1
)
assert (
len({
Channel(prefetch_count=10): 0,
Channel(prefetch_count=20): 1,
})
== 2
)
4 changes: 3 additions & 1 deletion tests/cli/test_publish.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,8 @@ def test_publish_nats_request_command(runner: CliRunner) -> None:

cmd: NatsPublishCommand = producer_mock.request.call_args.args[0]

import math

assert cmd.destination == "subjectname"
assert cmd.timeout == 1.0
assert math.isclose(cmd.timeout, 1.0)
assert cmd.publish_type is PublishType.REQUEST