2424import vfxnaming .rules as rules
2525import vfxnaming .tokens as tokens
2626from pathlib import Path
27- from typing import AnyStr , Dict , Union
27+ from typing import AnyStr , Dict , Union , Iterable
2828
2929from vfxnaming .logger import logger
3030from vfxnaming .error import SolvingError , RepoError
@@ -138,9 +138,12 @@ def solve(*args, **kwargs) -> AnyStr:
138138 return rule .solve (** values )
139139
140140
141- def validate (name : AnyStr , ** kwargs ) -> bool :
142- """Validates a name string against the currently active rule and its
143- tokens if passed as keyword arguments.
141+ def validate ( # noqa: C901
142+ name : AnyStr , with_rules : Iterable [str ] = [], strict : bool = False , ** kwargs
143+ ) -> Iterable [rules .Rule ]:
144+ """Validates a name string against the currently active rule if no rules are passed or
145+ against the list of specific rules passed in with_rules.
146+ It also validates its tokens if passed as keyword arguments.
144147
145148 -For rules with repeated tokens:
146149
@@ -162,50 +165,77 @@ def validate(name: AnyStr, **kwargs) -> bool:
162165 Args:
163166 name (str): Name string e.g.: C_helmet_001_MSH
164167
168+ with_rules (list, optional): List of rule names to validate against. Defaults to [].
169+
170+ strict (bool, optional): If False, it'll try to accept casing mismatches.
171+
165172 kwargs (dict): Keyword arguments with token names and values.
166173
167174 Returns:
168- bool: True if the name is valid, False otherwise .
175+ list: List of validated rules. Empty list if no rule could be validated .
169176 """
170- rule = rules .get_active_rule ()
171- # * This accounts for those cases where a token is used more than once in a rule
172- repeated_fields = dict ()
173- for each in rule .fields :
174- if each not in repeated_fields .keys ():
175- if rule .fields .count (each ) > 1 :
176- repeated_fields [each ] = 1
177- fields_with_digits = list ()
178- for each in rule .fields :
179- if each in repeated_fields .keys ():
180- counter = repeated_fields .get (each )
181- repeated_fields [each ] = counter + 1
182- fields_with_digits .append (f"{ each } { counter } " )
183- else :
184- fields_with_digits .append (each )
185- values = {}
186- fields_inc = 0
187- for f in fields_with_digits :
188- token = tokens .get_token (rule .fields [fields_inc ])
189- if token :
190- # Explicitly passed as keyword argument
191- if kwargs .get (f ) is not None :
192- values [f ] = token .solve (kwargs .get (f ))
193- fields_inc += 1
194- continue
195- # Explicitly passed as keyword argument without repetitive digits
196- # Use passed argument for all field repetitions
197- elif kwargs .get (rule .fields [fields_inc ]) is not None :
198- values [f ] = token .solve (kwargs .get (rule .fields [fields_inc ]))
199- fields_inc += 1
200- continue
201- elif token .required and isinstance (token , tokens .Token ):
202- if len (token .fallback ):
203- values [f ] = token .fallback
177+ previously_active_rule = rules .get_active_rule ()
178+ if not len (with_rules ):
179+ with_rules = [previously_active_rule .name ]
180+ validated : Iterable [rules .Rule ] = []
181+ for with_rule in with_rules :
182+ rule = rules .get_rule (with_rule )
183+ if not rule :
184+ logger .warning (f"Rule { with_rule } not found." )
185+
186+ rules .set_active_rule (rule )
187+ # * This accounts for those cases where a token is used more than once in a rule
188+ repeated_fields = dict ()
189+ for each in rule .fields :
190+ if each not in repeated_fields .keys ():
191+ if rule .fields .count (each ) > 1 :
192+ repeated_fields [each ] = 1
193+ fields_with_digits = list ()
194+ for each in rule .fields :
195+ if each in repeated_fields .keys ():
196+ counter = repeated_fields .get (each )
197+ repeated_fields [each ] = counter + 1
198+ fields_with_digits .append (f"{ each } { counter } " )
199+ else :
200+ fields_with_digits .append (each )
201+ values = {}
202+ fields_inc = 0
203+ for f in fields_with_digits :
204+ token = tokens .get_token (rule .fields [fields_inc ])
205+ if token :
206+ # Explicitly passed as keyword argument
207+ if kwargs .get (f ) is not None :
208+ values [f ] = token .solve (kwargs .get (f ))
204209 fields_inc += 1
205210 continue
206- fields_inc += 1
207- logger .debug (f"Validating rule '{ rule .name } ' with values { values } " )
208- return rule .validate (name , ** values )
211+ # Explicitly passed as keyword argument without repetitive digits
212+ # Use passed argument for all field repetitions
213+ elif kwargs .get (rule .fields [fields_inc ]) is not None :
214+ values [f ] = token .solve (kwargs .get (rule .fields [fields_inc ]))
215+ fields_inc += 1
216+ continue
217+ elif token .required and isinstance (token , tokens .Token ):
218+ if len (token .fallback ):
219+ values [f ] = token .fallback
220+ fields_inc += 1
221+ continue
222+ fields_inc += 1
223+ logger .debug (f"Validating rule '{ rule .name } ' with values { values } " )
224+ validation = rule .validate (name , strict , ** values )
225+ if validation :
226+ rules .set_active_rule (previously_active_rule )
227+ validated .append (rule )
228+ rules .set_active_rule (previously_active_rule )
229+ if not len (validated ):
230+ logger .warning (
231+ f"Could not validate { name } with any of the given "
232+ f"rules { ', ' .join ([rule for rule in with_rules ])} ."
233+ )
234+ else :
235+ logger .info (
236+ f"Name { name } validated with rules: { ', ' .join ([rule .name for rule in validated ])} ."
237+ )
238+ return validated
209239
210240
211241def validate_repo (repo : Path ) -> bool :
0 commit comments