99 Optional ,
1010 Sequence ,
1111 Tuple ,
12+ Union ,
1213)
1314
1415from eth_abi .codec import (
2324 TypeStr ,
2425)
2526from eth_utils import (
27+ is_hex ,
2628 is_list_like ,
2729 is_string ,
2830 is_text ,
4648from web3 ._utils .validation import (
4749 validate_address ,
4850)
51+ from web3 .exceptions import (
52+ ValidationError ,
53+ )
4954from web3 .types import (
5055 ABIEvent ,
5156 BlockIdentifier ,
5257 FilterParams ,
5358 LogReceipt ,
59+ RPCEndpoint ,
5460)
5561
5662if TYPE_CHECKING :
5763 from web3 import Web3 # noqa: F401
64+ from web3 .module import ( # noqa: F401
65+ Module ,
66+ ModuleV2 ,
67+ )
68+ from web3 .eth import Eth # noqa: F401
5869
5970
6071def construct_event_filter_params (
@@ -122,14 +133,16 @@ class Filter:
122133 poll_interval = None
123134 filter_id = None
124135
125- def __init__ (self , web3 : "Web3" , filter_id : HexStr ) -> None :
126- self .web3 = web3
136+ def __init__ (self ,
137+ filter_id : HexStr ,
138+ eth_module : "Eth" ) -> None :
139+ self .eth_module = eth_module
127140 self .filter_id = filter_id
128141 self .callbacks = []
129142 super ().__init__ ()
130143
131144 def __str__ (self ) -> str :
132- return "Filter for {0}" . format ( self .filter_id )
145+ return f "Filter for { self .filter_id } "
133146
134147 def format_entry (self , entry : LogReceipt ) -> LogReceipt :
135148 """
@@ -148,11 +161,11 @@ def _filter_valid_entries(self, entries: Collection[LogReceipt]) -> Iterator[Log
148161 return filter (self .is_valid_entry , entries )
149162
150163 def get_new_entries (self ) -> List [LogReceipt ]:
151- log_entries = self ._filter_valid_entries (self .web3 . eth .getFilterChanges (self .filter_id ))
164+ log_entries = self ._filter_valid_entries (self .eth_module .getFilterChanges (self .filter_id ))
152165 return self ._format_log_entries (log_entries )
153166
154167 def get_all_entries (self ) -> List [LogReceipt ]:
155- log_entries = self ._filter_valid_entries (self .web3 . eth .getFilterLogs (self .filter_id ))
168+ log_entries = self ._filter_valid_entries (self .eth_module .getFilterLogs (self .filter_id ))
156169 return self ._format_log_entries (log_entries )
157170
158171 def _format_log_entries (self ,
@@ -203,7 +216,7 @@ def set_data_filters(self, data_filter_set: Collection[Tuple[TypeStr, Any]]) ->
203216 """
204217 self .data_filter_set = data_filter_set
205218 if any (data_filter_set ):
206- self .data_filter_set_function = match_fn (self .web3 , data_filter_set )
219+ self .data_filter_set_function = match_fn (self .eth_module . codec , data_filter_set )
207220
208221 def is_valid_entry (self , entry : LogReceipt ) -> bool :
209222 if not self .data_filter_set :
@@ -235,21 +248,21 @@ def normalize_data_values(type_string: TypeStr, data_value: Any) -> Any:
235248
236249
237250@curry
238- def match_fn (w3 : "Web3" , match_values_and_abi : Collection [Tuple [str , Any ]], data : Any ) -> bool :
251+ def match_fn (codec : ABICodec , match_values_and_abi : Collection [Tuple [str , Any ]], data : Any ) -> bool :
239252 """Match function used for filtering non-indexed event arguments.
240253
241254 Values provided through the match_values_and_abi parameter are
242255 compared to the abi decoded log data.
243256 """
244257 abi_types , all_match_values = zip (* match_values_and_abi )
245258
246- decoded_values = w3 . codec .decode_abi (abi_types , HexBytes (data ))
259+ decoded_values = codec .decode_abi (abi_types , HexBytes (data ))
247260 for data_value , match_values , abi_type in zip (decoded_values , all_match_values , abi_types ):
248261 if match_values is None :
249262 continue
250263 normalized_data = normalize_data_values (abi_type , data_value )
251264 for value in match_values :
252- if not w3 .is_encodable (abi_type , value ):
265+ if not codec .is_encodable (abi_type , value ):
253266 raise ValueError (
254267 f"Value { value } is of the wrong abi type. "
255268 f"Expected { abi_type } typed value."
@@ -260,3 +273,41 @@ def match_fn(w3: "Web3", match_values_and_abi: Collection[Tuple[str, Any]], data
260273 return False
261274
262275 return True
276+
277+
278+ class _UseExistingFilter (Exception ):
279+ """
280+ Internal exception, raised when a filter_id is passed into w3.eth.filter()
281+ """
282+ def __init__ (
283+ self ,
284+ filter_id : Union [str , FilterParams , HexStr ]
285+ ) -> None :
286+ self .filter_id = filter_id
287+
288+
289+ @curry
290+ def select_filter_method (
291+ value : Union [str , FilterParams , HexStr ],
292+ if_new_block_filter : RPCEndpoint ,
293+ if_new_pending_transaction_filter : RPCEndpoint ,
294+ if_new_filter : RPCEndpoint ,
295+ ) -> RPCEndpoint :
296+
297+ if is_string (value ):
298+ if value == "latest" :
299+ return if_new_block_filter
300+ elif value == "pending" :
301+ return if_new_pending_transaction_filter
302+ elif is_hex (value ):
303+ raise _UseExistingFilter (value )
304+ else :
305+ raise ValidationError ("Filter argument needs to be either 'latest',"
306+ " 'pending', or a hex-encoded filter_id. Filter argument"
307+ f" is: { value } " )
308+ elif isinstance (value , dict ):
309+ return if_new_filter
310+ else :
311+ raise ValidationError ("Filter argument needs to be either the string "
312+ "'pending' or 'latest', a filter_id, "
313+ f"or a filter params dictionary. Filter argument is: { value } " )
0 commit comments