(callback_map)
| 533 | |
| 534 | |
| 535 | def validate_background_callbacks(callback_map): |
| 536 | # Validate that background callback side output & inputs are not circular |
| 537 | # If circular, triggering a background callback would result in a fatal server/computer crash. |
| 538 | all_outputs = set() |
| 539 | input_indexed = {} |
| 540 | for callback in callback_map.values(): |
| 541 | out = coerce_to_list(callback["output"]) |
| 542 | all_outputs.update(out) |
| 543 | for o in out: |
| 544 | input_indexed.setdefault(o, set()) |
| 545 | input_indexed[o].update(coerce_to_list(callback["raw_inputs"])) |
| 546 | |
| 547 | for callback in (x for x in callback_map.values() if x.get("background")): |
| 548 | bg_info = callback["background"] |
| 549 | progress = bg_info.get("progress", []) |
| 550 | running = bg_info.get("running", []) |
| 551 | |
| 552 | bg_inputs = coerce_to_list(callback["raw_inputs"]) |
| 553 | outputs = set([x[0] for x in running] + progress) |
| 554 | circular = [ |
| 555 | x |
| 556 | for x in set(k for k, v in input_indexed.items() if v.intersection(outputs)) |
| 557 | if x in bg_inputs |
| 558 | ] |
| 559 | |
| 560 | if circular: |
| 561 | raise exceptions.BackgroundCallbackError( |
| 562 | f"Background callback circular error!\n{circular} is used as input for a background callback" |
| 563 | f" but also used as output from an input that is updated with progress or running argument." |
| 564 | ) |
| 565 | |
| 566 | |
| 567 | def validate_duplicate_output( |
searching dependent graphs…