11# -*- coding: utf-8 -*-
22from __future__ import annotations
33
4- from typing import TYPE_CHECKING , Any , Callable , Hashable , Pattern , Protocol
4+ import re
5+ from typing import TYPE_CHECKING , Any , Callable , Hashable , Protocol
56
67if TYPE_CHECKING :
78 # identifiers for subscribers
@@ -23,8 +24,8 @@ def add_rpc_subscriber(self, subscriber: 'RpcSubscriber', identifier: 'ID_TYPE |
2324 def add_broadcast_subscriber (
2425 self ,
2526 subscriber : 'BroadcastSubscriber' ,
26- subject_filters : list [Hashable | Pattern [str ]] | None = None ,
27- sender_filters : list [Hashable | Pattern [str ]] | None = None ,
27+ subject_filters : list [Hashable | re . Pattern [str ]] | None = None ,
28+ sender_filters : list [Hashable | re . Pattern [str ]] | None = None ,
2829 identifier : 'ID_TYPE | None' = None ,
2930 ) -> Any : ...
3031
@@ -50,3 +51,58 @@ def broadcast_send(
5051 def task_send (self , task : Any , no_reply : bool = False ) -> Any : ...
5152
5253 def close (self ) -> None : ...
54+
55+
56+ class BroadcastFilter :
57+ """A filter that can be used to limit the subjects and/or senders that will be received"""
58+
59+ def __init__ (self , subscriber , subject = None , sender = None ): # type: ignore
60+ self ._subscriber = subscriber
61+ self ._subject_filters = []
62+ self ._sender_filters = []
63+ if subject is not None :
64+ self .add_subject_filter (subject )
65+ if sender is not None :
66+ self .add_sender_filter (sender )
67+
68+ @property
69+ def __name__ (self ): # type: ignore
70+ return 'BroadcastFilter'
71+
72+ def __call__ (self , communicator , body , sender = None , subject = None , correlation_id = None ): # type: ignore
73+ if self .is_filtered (sender , subject ):
74+ return None
75+ return self ._subscriber (communicator , body , sender , subject , correlation_id )
76+
77+ def is_filtered (self , sender , subject ) -> bool : # type: ignore
78+ if subject is not None and self ._subject_filters and not any (check (subject ) for check in self ._subject_filters ):
79+ return True
80+
81+ if sender is not None and self ._sender_filters and not any (check (sender ) for check in self ._sender_filters ):
82+ return True
83+
84+ return False
85+
86+ def add_subject_filter (self , subject_filter : re .Pattern [str ] | None ) -> None :
87+ self ._subject_filters .append (self ._ensure_filter (subject_filter )) # type: ignore
88+
89+ def add_sender_filter (self , sender_filter : re .Pattern [str ]) -> None :
90+ self ._sender_filters .append (self ._ensure_filter (sender_filter )) # type: ignore
91+
92+ @classmethod
93+ def _ensure_filter (cls , filter_value ): # type: ignore
94+ if isinstance (filter_value , str ):
95+ return re .compile (filter_value .replace ('.' , '[.]' ).replace ('*' , '.*' )).match
96+ if isinstance (filter_value , re .Pattern ): # pylint: disable=isinstance-second-argument-not-valid-type
97+ return filter_value .match
98+
99+ return lambda val : val == filter_value
100+
101+ @classmethod
102+ def _make_regex (cls , filter_str ): # type: ignore
103+ """
104+ :param filter_str: The filter string
105+ :type filter_str: str
106+ :return: The regular expression object
107+ """
108+ return re .compile (filter_str .replace ('.' , '[.]' ))
0 commit comments