21
21
extract_fields_from_class ,
22
22
ensure_field_objects ,
23
23
build_task_class ,
24
+ sanitize_xor ,
24
25
NO_DEFAULT ,
25
26
)
26
27
from pydra .utils .typing import (
@@ -208,7 +209,7 @@ def make(
208
209
)
209
210
210
211
# Set positions for the remaining inputs that don't have an explicit position
211
- position_stack = remaining_positions (list (parsed_inputs .values ()))
212
+ position_stack = remaining_positions (list (parsed_inputs .values ()), xor = xor )
212
213
for inpt in parsed_inputs .values ():
213
214
if inpt .name == "append_args" :
214
215
continue
@@ -526,7 +527,10 @@ def from_type_str(type_str) -> type:
526
527
527
528
528
529
def remaining_positions (
529
- args : list [Arg ], num_args : int | None = None , start : int = 0
530
+ args : list [Arg ],
531
+ num_args : int | None = None ,
532
+ start : int = 0 ,
533
+ xor : set [frozenset [str ]] | None = None ,
530
534
) -> ty .List [int ]:
531
535
"""Get the remaining positions for input fields
532
536
@@ -536,6 +540,10 @@ def remaining_positions(
536
540
The list of input fields
537
541
num_args : int, optional
538
542
The number of arguments, by default it is the length of the args
543
+ start : int, optional
544
+ The starting position, by default 0
545
+ xor : set[frozenset[str]], optional
546
+ A set of mutually exclusive fields, by default None
539
547
540
548
Returns
541
549
-------
@@ -547,6 +555,7 @@ def remaining_positions(
547
555
ValueError
548
556
If multiple fields have the same position
549
557
"""
558
+ xor = sanitize_xor (xor )
550
559
if num_args is None :
551
560
num_args = len (args ) - 1 # Subtract 1 for the 'append_args' field
552
561
# Check for multiple positions
@@ -562,7 +571,7 @@ def remaining_positions(
562
571
if multiple_positions := {
563
572
k : [f"{ a .name } ({ a .position } )" for a in v ]
564
573
for k , v in positions .items ()
565
- if len (v ) > 1
574
+ if len (v ) > 1 and not any ( x . issuperset ( a . name for a in v ) for x in xor )
566
575
}:
567
576
raise ValueError (
568
577
f"Multiple fields have the overlapping positions: { multiple_positions } "
0 commit comments