1616# along with this program. If not, see <http://www.gnu.org/licenses/>.
1717
1818import dataclasses
19- from typing import Any ,Optional ,Tuple ,TYPE_CHECKING
19+ from typing import Any ,Dict , List , Optional ,Tuple ,TYPE_CHECKING
2020
2121
2222@dataclasses .dataclass (frozen = True )
@@ -25,6 +25,33 @@ class RequiredOptional:
2525optional :Tuple [str , ...]= ()
2626exclusive :Tuple [str , ...]= ()
2727
28+ def validate_attrs (
29+ self ,
30+ * ,
31+ data :Dict [str ,Any ],
32+ excludes :Optional [List [str ]]= None ,
33+ )-> None :
34+ if excludes is None :
35+ excludes = []
36+
37+ if self .required :
38+ required = [k for k in self .required if k not in excludes ]
39+ missing = [attr for attr in required if attr not in data ]
40+ if missing :
41+ raise AttributeError (f"Missing attributes:{ ', ' .join (missing )} " )
42+
43+ if self .exclusive :
44+ exclusives = [attr for attr in data if attr in self .exclusive ]
45+ if len (exclusives )> 1 :
46+ raise AttributeError (
47+ f"Provide only one of these attributes:{ ', ' .join (exclusives )} "
48+ )
49+ if not exclusives :
50+ raise AttributeError (
51+ f"Must provide one of these attributes: "
52+ f"{ ', ' .join (self .exclusive )} "
53+ )
54+
2855
2956class GitlabAttribute :
3057def __init__ (self ,value :Any = None )-> None :