88import random
99import re
1010from collections .abc import Container , Iterable , Mapping
11- from typing import Any , Callable , Union
11+ from typing import TYPE_CHECKING , Any , Callable , Dict , TypeVar , Union , overload
1212
1313import jaraco .text
1414
15+ if TYPE_CHECKING :
16+ from _typeshed import SupportsKeysAndGetItem
17+ from typing_extensions import Self
18+
19+ _T = TypeVar ('_T' )
20+ _VT = TypeVar ('_VT' )
21+
1522_Matchable = Union [Callable , Container , Iterable , re .Pattern ]
1623
1724
@@ -119,7 +126,7 @@ def dict_map(function, dictionary):
119126 return dict ((key , function (value )) for key , value in dictionary .items ())
120127
121128
122- class RangeMap (dict ):
129+ class RangeMap (Dict [ int , _VT ] ):
123130 """
124131 A dictionary-like object that uses the keys as bounds for a range.
125132 Inclusion of the value for that range is determined by the
@@ -186,7 +193,7 @@ class RangeMap(dict):
186193 which requires use of sort params and a key_match_comparator.
187194
188195 >>> r = RangeMap({1: 'a', 4: 'b'},
189- ... sort_params=dict( reverse= True) ,
196+ ... sort_params={' reverse': True} ,
190197 ... key_match_comparator=operator.ge)
191198 >>> r[1], r[2], r[3], r[4], r[5], r[6]
192199 ('a', 'a', 'a', 'b', 'b', 'b')
@@ -202,21 +209,23 @@ class RangeMap(dict):
202209
203210 def __init__ (
204211 self ,
205- source ,
212+ source : SupportsKeysAndGetItem [ int , _VT ] | Iterable [ tuple [ int , _VT ]] ,
206213 sort_params : Mapping [str , Any ] = {},
207- key_match_comparator = operator .le ,
214+ key_match_comparator : Callable [[ int , int ], bool ] = operator .le ,
208215 ):
209216 dict .__init__ (self , source )
210217 self .sort_params = sort_params
211218 self .match = key_match_comparator
212219
213220 @classmethod
214- def left (cls , source ):
221+ def left (
222+ cls , source : SupportsKeysAndGetItem [int , _VT ] | Iterable [tuple [int , _VT ]]
223+ ) -> Self :
215224 return cls (
216- source , sort_params = dict ( reverse = True ) , key_match_comparator = operator .ge
225+ source , sort_params = { ' reverse' : True } , key_match_comparator = operator .ge
217226 )
218227
219- def __getitem__ (self , item ) :
228+ def __getitem__ (self , item : int ) -> _VT :
220229 sorted_keys = sorted (self .keys (), ** self .sort_params )
221230 if isinstance (item , RangeMap .Item ):
222231 result = self .__getitem__ (sorted_keys [item ])
@@ -227,7 +236,11 @@ def __getitem__(self, item):
227236 raise KeyError (key )
228237 return result
229238
230- def get (self , key , default = None ):
239+ @overload # type: ignore[override] # Signature simplified over dict and Mapping
240+ def get (self , key : int , default : _T ) -> _VT | _T : ...
241+ @overload
242+ def get (self , key : int , default : None = None ) -> _VT | None : ...
243+ def get (self , key : int , default : _T | None = None ) -> _VT | _T | None :
231244 """
232245 Return the value for key if key is in the dictionary, else default.
233246 If default is not given, it defaults to None, so that this method
@@ -238,22 +251,23 @@ def get(self, key, default=None):
238251 except KeyError :
239252 return default
240253
241- def _find_first_match_ (self , keys , item ) :
254+ def _find_first_match_ (self , keys : Iterable [ int ] , item : int ) -> int :
242255 is_match = functools .partial (self .match , item )
243- matches = list (filter (is_match , keys ))
244- if matches :
245- return matches [0 ]
246- raise KeyError (item )
256+ matches = filter (is_match , keys )
257+ try :
258+ return next (matches )
259+ except StopIteration :
260+ raise KeyError (item ) from None
247261
248- def bounds (self ):
262+ def bounds (self ) -> tuple [ int , int ] :
249263 sorted_keys = sorted (self .keys (), ** self .sort_params )
250264 return (sorted_keys [RangeMap .first_item ], sorted_keys [RangeMap .last_item ])
251265
252266 # some special values for the RangeMap
253267 undefined_value = type ('RangeValueUndefined' , (), {})()
254268
255269 class Item (int ):
256- " RangeMap Item"
270+ ' RangeMap Item'
257271
258272 first_item = Item (0 )
259273 last_item = Item (- 1 )
0 commit comments