(self, config_string, strict=False)
| 644 | validate_label_config(config_string) |
| 645 | |
| 646 | def validate_config(self, config_string, strict=False): |
| 647 | self.validate_label_config(config_string) |
| 648 | if not hasattr(self, 'summary'): |
| 649 | return |
| 650 | |
| 651 | with transaction.atomic(): |
| 652 | # Lock summary for update to avoid race conditions |
| 653 | summary = ProjectSummary.objects.select_for_update().get(project=self) |
| 654 | |
| 655 | if self.num_tasks == 0: |
| 656 | logger.debug(f'Project {self} has no tasks: nothing to validate here. Ensure project summary is empty') |
| 657 | summary.reset() |
| 658 | return |
| 659 | |
| 660 | # validate data columns consistency |
| 661 | fields_from_config = get_all_object_tag_names(config_string) |
| 662 | if not fields_from_config: |
| 663 | logger.debug('Data fields not found in labeling config') |
| 664 | return |
| 665 | |
| 666 | # TODO: DEV-2939 Add validation for fields addition in label config |
| 667 | """fields_from_config = {field.split('[')[0] for field in fields_from_config} # Repeater tag support |
| 668 | fields_from_data = set(self.summary.common_data_columns) |
| 669 | fields_from_data.discard(settings.DATA_UNDEFINED_NAME) |
| 670 | if fields_from_data and not fields_from_config.issubset(fields_from_data): |
| 671 | different_fields = list(fields_from_config.difference(fields_from_data)) |
| 672 | raise ValidationError( |
| 673 | f'These fields are not present in the data: {",".join(different_fields)}' |
| 674 | )""" |
| 675 | |
| 676 | if self.num_annotations == 0 and self.num_drafts == 0: |
| 677 | logger.debug( |
| 678 | f'Project {self} has no annotations and drafts: nothing to validate here. ' |
| 679 | f'Ensure annotations-related project summary is empty' |
| 680 | ) |
| 681 | summary.reset(tasks_data_based=False) |
| 682 | return |
| 683 | |
| 684 | # validate annotations consistency |
| 685 | annotations_from_config = set(get_all_control_tag_tuples(config_string)) |
| 686 | if not annotations_from_config: |
| 687 | logger.debug('Annotation schema is not found in config') |
| 688 | return |
| 689 | annotations_from_data = set(self.summary.created_annotations) |
| 690 | if annotations_from_data and not annotations_from_data.issubset(annotations_from_config): |
| 691 | different_annotations = list(annotations_from_data.difference(annotations_from_config)) |
| 692 | diff_str = [] |
| 693 | for ann_tuple in different_annotations: |
| 694 | from_name, to_name, t = ann_tuple.split('|') |
| 695 | # TODO tags that operate as both object and control tags; should be special registry/logic for them |
| 696 | if from_name == to_name and t.lower() == 'chatmessage': |
| 697 | continue |
| 698 | if t.lower() == 'textarea': # avoid textarea to_name check (see DEV-1598) |
| 699 | continue |
| 700 | if ( |
| 701 | not check_control_in_config_by_regex(config_string, from_name) |
| 702 | or not check_toname_in_config_by_regex(config_string, to_name) |
| 703 | or t not in get_all_types(config_string) |
no test coverage detected