@@ -471,37 +471,24 @@ def parse_graph(self, graph_string: str) -> None:
471
471
pairs .add ((chain [i ], chain [i + 1 ]))
472
472
473
473
# Get a set of RH nodes which are not at the LH of another pair:
474
- self . terminals = self . get_graph_terminals ( pairs )
474
+ # terminals = {p[1] for p in pairs}.difference({p[0] for p in pairs} )
475
475
476
- for pair in sorted (pairs , key = lambda p : str (p [0 ])):
477
- self ._proc_dep_pair (pair , self .terminals )
478
-
479
- @staticmethod
480
- def get_graph_terminals (pairs ):
481
- """Get terminating ends of graphs.
476
+ check_terminals = {}
477
+ lefts = set ()
478
+ rights = set ()
482
479
483
- For example in `foo => bar => baz` only `baz` terminates the chain
484
- of dependencies.
480
+ for pair in sorted ( pairs , key = lambda p : str ( p [ 0 ])):
481
+ self . _proc_dep_pair ( pair , check_terminals , lefts , rights )
485
482
486
- Examples:
487
- >>> this = GraphParser.get_graph_terminals
488
- >>> this({('foo', 'bar')})
489
- {'bar'}
490
- """
491
- lefts = []
492
- rights = []
493
- for left , right in pairs :
494
- if left and ('&' in left or '|' in left ):
495
- # RE used because don't want to have to worry about
496
- # mutiple and/or and cleaning whitespace.
497
- lefts += GraphParser ._RE_ANDOR .split (left )
498
- else :
499
- lefts .append (left )
500
- if right and ('&' in right or '|' in right ):
501
- rights += GraphParser ._RE_ANDOR .split (right )
502
- else :
503
- rights .append (right )
504
- return set (rights ).difference (set (lefts ))
483
+ self .terminals = rights .difference (lefts )
484
+ for right in self .terminals :
485
+ left = check_terminals .get (right )
486
+ if left :
487
+ raise GraphParseError (
488
+ 'Invalid cycle point offsets only on right hand'
489
+ ' side of dependency (must be on left hand side):'
490
+ f'{ left } => { right } '
491
+ )
505
492
506
493
@classmethod
507
494
def _report_invalid_lines (cls , lines : List [str ]) -> None :
@@ -532,7 +519,9 @@ def _report_invalid_lines(cls, lines: List[str]) -> None:
532
519
def _proc_dep_pair (
533
520
self ,
534
521
pair : Tuple [Optional [str ], str ],
535
- terminals : Set [str ],
522
+ check_terminals : Dict [str , str ],
523
+ _lefts : Set [str ],
524
+ _rights : Set [str ],
536
525
) -> None :
537
526
"""Process a single dependency pair 'left => right'.
538
527
@@ -568,12 +557,8 @@ def _proc_dep_pair(
568
557
raise GraphParseError (mismatch_msg .format (right ))
569
558
570
559
# Raise error for cycle point offsets at the end of chains
571
- if '[' in right and left and (right in terminals ):
572
- # This right hand side is at the end of a chain:
573
- raise GraphParseError (
574
- 'Invalid cycle point offsets only on right hand '
575
- 'side of a dependency (must be on left hand side):'
576
- f' { left } => { right } ' )
560
+ if '[' in right and left :
561
+ check_terminals [right ] = left
577
562
578
563
# Split right side on AND.
579
564
rights = right .split (self .__class__ .OP_AND )
@@ -594,12 +579,15 @@ def _proc_dep_pair(
594
579
raise GraphParseError (
595
580
f"Null task name in graph: { left } => { right } " )
596
581
582
+ _rights .update (* ([rights ] or []))
583
+
597
584
for left in lefts :
598
585
# Extract information about all nodes on the left.
599
586
600
587
if left :
601
588
info = self .__class__ .REC_NODES .findall (left )
602
589
expr = left
590
+ _lefts .add (left )
603
591
604
592
else :
605
593
# There is no left-hand-side task.
0 commit comments