@@ -129,8 +129,7 @@ def _get_list_of_markers(d: Dict[str, Any], key: str) -> Optional[List[Marker]]:
129
129
result .append (Marker (item ))
130
130
except InvalidMarker :
131
131
raise PylockValidationError (
132
- f"Item { i } in list { key !r} "
133
- f"is not a valid environment marker: { item !r} "
132
+ f"Item { i } in list { key !r} is not a valid environment marker: { item !r} "
134
133
)
135
134
return result
136
135
@@ -186,14 +185,14 @@ def _get_required_list_of_objects(
186
185
return result
187
186
188
187
189
- def _validate_exactly_one_of ( o : object , attrs : List [ str ]) -> None :
190
- """Validate that exactly one of the attributes is truthy."""
191
- count = 0
192
- for attr in attrs :
193
- if getattr ( o , attr ) :
194
- count += 1
195
- if count != 1 :
196
- raise PylockValidationError ( f"Exactly one of { ', ' . join ( attrs ) } must be set" )
188
+ def _exactly_one ( iterable : Iterable [ object ]) -> bool :
189
+ found = False
190
+ for item in iterable :
191
+ if item :
192
+ if found :
193
+ return False
194
+ found = True
195
+ return found
197
196
198
197
199
198
class PylockValidationError (Exception ):
@@ -221,7 +220,8 @@ class PackageVcs:
221
220
222
221
def __post_init__ (self ) -> None :
223
222
# TODO validate supported vcs type
224
- _validate_exactly_one_of (self , ["url" , "path" ])
223
+ if not self .path and not self .url :
224
+ raise PylockValidationError ("No path nor url set for vcs package" )
225
225
226
226
@classmethod
227
227
def from_dict (cls , d : Dict [str , Any ]) -> Self :
@@ -260,7 +260,8 @@ class PackageArchive:
260
260
subdirectory : Optional [str ]
261
261
262
262
def __post_init__ (self ) -> None :
263
- _validate_exactly_one_of (self , ["url" , "path" ])
263
+ if not self .path and not self .url :
264
+ raise PylockValidationError ("No path nor url set for archive package" )
264
265
265
266
@classmethod
266
267
def from_dict (cls , d : Dict [str , Any ]) -> Self :
@@ -283,7 +284,8 @@ class PackageSdist:
283
284
hashes : Dict [str , str ]
284
285
285
286
def __post_init__ (self ) -> None :
286
- _validate_exactly_one_of (self , ["url" , "path" ])
287
+ if not self .path and not self .url :
288
+ raise PylockValidationError ("No path nor url set for sdist package" )
287
289
288
290
@classmethod
289
291
def from_dict (cls , d : Dict [str , Any ]) -> Self :
@@ -306,7 +308,8 @@ class PackageWheel:
306
308
hashes : Dict [str , str ]
307
309
308
310
def __post_init__ (self ) -> None :
309
- _validate_exactly_one_of (self , ["url" , "path" ])
311
+ if not self .path and not self .url :
312
+ raise PylockValidationError ("No path nor url set for wheel package" )
310
313
311
314
@classmethod
312
315
def from_dict (cls , d : Dict [str , Any ]) -> Self :
@@ -337,9 +340,19 @@ class Package:
337
340
# (not supported) tool: Optional[Dict[str, Any]]
338
341
339
342
def __post_init__ (self ) -> None :
340
- _validate_exactly_one_of (
341
- self , ["vcs" , "directory" , "archive" , "sdist" , "wheels" ]
342
- )
343
+ if self .sdist or self .wheels :
344
+ if any ([self .vcs , self .directory , self .archive ]):
345
+ raise PylockValidationError (
346
+ "None of vcs, directory, archive "
347
+ "must be set if sdist or wheels are set"
348
+ )
349
+ else :
350
+ # no sdist nor wheels
351
+ if not _exactly_one ([self .vcs , self .directory , self .archive ]):
352
+ raise PylockValidationError (
353
+ "Exactly one of vcs, directory, archive must be set "
354
+ "if sdist and wheels are not set"
355
+ )
343
356
344
357
@classmethod
345
358
def from_dict (cls , d : Dict [str , Any ]) -> Self :
0 commit comments