@@ -181,7 +181,7 @@ def match(self, obj: Repository|PullRequest,
181181 # NOTE(aznashwan): Only Repositories/PRs have associated files.
182182 if not isinstance (obj , (Repository , PullRequest )):
183183 LOG .warn (
184- f"FileSelector got unsupported object type { type (obj )} : { obj } " )
184+ f"{ self . __class__ } .match() got unsupported object type { type (obj )} : { obj } " )
185185 return []
186186
187187 all_files = file_cache
@@ -199,6 +199,74 @@ def match(self, obj: Repository|PullRequest,
199199 return res
200200
201201
202+ class LinesChangedSelector (Selector ):
203+
204+ def __init__ (
205+ self , min : int | None = None , max : int | None = None ,
206+ change_type : str = "total" ):
207+ if min is None and max is None :
208+ raise ValueError (
209+ f"{ self .__class__ } : at least one of min/max is required." )
210+ self ._min = min
211+ self ._max = max
212+ supported_change_types = [
213+ "additions" , "deletions" , "total" , "net" ]
214+ if change_type not in supported_change_types :
215+ raise ValueError (
216+ f"Unsupported change type { change_type } . "
217+ f"Must be one of: { supported_change_types } " )
218+ self ._change_type = change_type
219+
220+ @classmethod
221+ def from_dict (cls , val : dict ):
222+ supported_keys = ["min" , "max" , "type" ]
223+ unsupported_keys = [k for k in val if k not in supported_keys ]
224+ if unsupported_keys :
225+ raise ValueError (
226+ f"{ cls } .from_dict() got unsupported keys: { unsupported_keys } " )
227+ return cls (
228+ min = val .get ("min" ), max = val .get ("max" ),
229+ change_type = val .get ("type" , "total" ))
230+
231+ def match (self , obj : Repository | PullRequest ,
232+ file_cache : list [str ]= []) -> list [dict ]:
233+ _ = file_cache
234+
235+ # NOTE(aznashwan): Only Repositories/PRs have associated files.
236+ if not isinstance (obj , (PullRequest , Repository )):
237+ LOG .warn (
238+ f"{ self .__class__ } .match() got unsupported object type { type (obj )} : { obj } " )
239+ return []
240+
241+ res = {
242+ "lines-changed-min" :
243+ self ._min if self ._min is not None else "-Inf" ,
244+ "lines-changed-max" :
245+ self ._max if self ._max is not None else "+Inf" }
246+ if isinstance (obj , Repository ):
247+ return [res ]
248+
249+ changes = 0
250+ match self ._change_type :
251+ case "total" :
252+ changes = obj .additions + obj .deletions
253+ case "additions" :
254+ changes = obj .additions
255+ case "deletions" :
256+ changes = obj .deletions
257+ case "net" :
258+ changes = obj .additions - obj .deletions
259+ case other :
260+ raise ValueError (
261+ f"Got unsupported change totalling scheme: { other } " )
262+
263+ if self ._min is not None and changes < self ._min :
264+ return []
265+ if self ._max is not None and changes >= self ._max :
266+ return []
267+ return [res ]
268+
269+
202270class FileLister ():
203271
204272 def __init__ (self , obj : Repository | PullRequest ):
@@ -231,6 +299,7 @@ def list_file_paths(self) -> list[str]:
231299SELECTORS_NAME_MAP = {
232300 "regex" : RegexSelector ,
233301 "files" : FilesSelector ,
302+ "lines-changed" : LinesChangedSelector ,
234303}
235304
236305
0 commit comments