@@ -372,9 +372,11 @@ def _filter_by_genres(
372372 session : Session ,
373373 values : Sequence [str ],
374374 match_all : bool = False ,
375+ match_none : bool = False ,
375376 ) -> Query :
376377 op = json_array_contains_all if match_all else json_array_contains_any
377- return query .filter (op (RomMetadata .genres , values , session = session ))
378+ condition = op (RomMetadata .genres , values , session = session )
379+ return query .filter (~ condition ) if match_none else query .filter (condition )
378380
379381 def _filter_by_franchises (
380382 self ,
@@ -383,9 +385,11 @@ def _filter_by_franchises(
383385 session : Session ,
384386 values : Sequence [str ],
385387 match_all : bool = False ,
388+ match_none : bool = False ,
386389 ) -> Query :
387390 op = json_array_contains_all if match_all else json_array_contains_any
388- return query .filter (op (RomMetadata .franchises , values , session = session ))
391+ condition = op (RomMetadata .franchises , values , session = session )
392+ return query .filter (~ condition ) if match_none else query .filter (condition )
389393
390394 def _filter_by_collections (
391395 self ,
@@ -394,9 +398,11 @@ def _filter_by_collections(
394398 session : Session ,
395399 values : Sequence [str ],
396400 match_all : bool = False ,
401+ match_none : bool = False ,
397402 ) -> Query :
398403 op = json_array_contains_all if match_all else json_array_contains_any
399- return query .filter (op (RomMetadata .collections , values , session = session ))
404+ condition = op (RomMetadata .collections , values , session = session )
405+ return query .filter (~ condition ) if match_none else query .filter (condition )
400406
401407 def _filter_by_companies (
402408 self ,
@@ -405,9 +411,11 @@ def _filter_by_companies(
405411 session : Session ,
406412 values : Sequence [str ],
407413 match_all : bool = False ,
414+ match_none : bool = False ,
408415 ) -> Query :
409416 op = json_array_contains_all if match_all else json_array_contains_any
410- return query .filter (op (RomMetadata .companies , values , session = session ))
417+ condition = op (RomMetadata .companies , values , session = session )
418+ return query .filter (~ condition ) if match_none else query .filter (condition )
411419
412420 def _filter_by_age_ratings (
413421 self ,
@@ -416,9 +424,11 @@ def _filter_by_age_ratings(
416424 session : Session ,
417425 values : Sequence [str ],
418426 match_all : bool = False ,
427+ match_none : bool = False ,
419428 ) -> Query :
420429 op = json_array_contains_all if match_all else json_array_contains_any
421- return query .filter (op (RomMetadata .age_ratings , values , session = session ))
430+ condition = op (RomMetadata .age_ratings , values , session = session )
431+ return query .filter (~ condition ) if match_none else query .filter (condition )
422432
423433 def _filter_by_status (self , query : Query , statuses : Sequence [str ]):
424434 """Filter by one or more user statuses using OR logic."""
@@ -449,9 +459,11 @@ def _filter_by_regions(
449459 session : Session ,
450460 values : Sequence [str ],
451461 match_all : bool = False ,
462+ match_none : bool = False ,
452463 ) -> Query :
453464 op = json_array_contains_all if match_all else json_array_contains_any
454- return query .filter (op (Rom .regions , values , session = session ))
465+ condition = op (Rom .regions , values , session = session )
466+ return query .filter (~ condition ) if match_none else query .filter (condition )
455467
456468 def _filter_by_languages (
457469 self ,
@@ -460,9 +472,11 @@ def _filter_by_languages(
460472 session : Session ,
461473 values : Sequence [str ],
462474 match_all : bool = False ,
475+ match_none : bool = False ,
463476 ) -> Query :
464477 op = json_array_contains_all if match_all else json_array_contains_any
465- return query .filter (op (Rom .languages , values , session = session ))
478+ condition = op (Rom .languages , values , session = session )
479+ return query .filter (~ condition ) if match_none else query .filter (condition )
466480
467481 def _filter_by_player_counts (
468482 self ,
@@ -471,8 +485,12 @@ def _filter_by_player_counts(
471485 session : Session ,
472486 values : Sequence [str ],
473487 match_all : bool = False ,
488+ match_none : bool = False ,
474489 ) -> Query :
475- return query .filter (RomMetadata .player_count .in_ (values ))
490+ condition = RomMetadata .player_count .in_ (values )
491+ if match_none :
492+ return query .filter (not_ (condition ))
493+ return query .filter (condition )
476494
477495 @begin_session
478496 def filter_roms (
@@ -695,7 +713,11 @@ def filter_roms(
695713 for values , logic , filter_func in filters_to_apply :
696714 if values :
697715 query = filter_func (
698- query , session = session , values = values , match_all = (logic == "all" )
716+ query ,
717+ session = session ,
718+ values = values ,
719+ match_all = (logic == "all" ),
720+ match_none = (logic == "none" ),
699721 )
700722
701723 # The RomUser table is already joined if user_id is set
0 commit comments