def _make_user_partition_groups(usage_key, group_access): """ Return a (Dict, Optional[ContentErrorData]) of user partition groups. The Dict is a mapping of user partition ID to list of group IDs. If any empty groups are encountered, we create a ContentErrorData about that. If there are no empty groups, we pass back (Dict, None). """ empty_partitions = sorted( part_id for part_id, group_ids in group_access.items() if not group_ids ) empty_partitions_txt = ", ".join([str(part_id) for part_id in empty_partitions]) if empty_partitions: error = ContentErrorData( message=( f'<{usage_key.block_type}> with url_name="{usage_key.block_id}"' f' has the following empty group_access user partitions: ' f'{empty_partitions_txt}. This would make this content ' f'unavailable to anyone except course staff. Ignoring these ' f'group_access settings when building outline.' ), usage_key=_remove_version_info(usage_key), ) else: error = None user_partition_groups = { part_id: group_ids for part_id, group_ids in group_access.items() if group_ids } return user_partition_groups, error
def _make_bubbled_up_error(seq_usage_key, user_partition_id, group_ids): return ContentErrorData( message= (f'<{seq_usage_key.block_type}> with url_name="{seq_usage_key.block_id}"' f' was assigned group_ids {group_ids} for user_partition_id ' f'{user_partition_id} because all of its child Units had that ' f'group_access setting. This is permitted, but is an unusual usage ' f'that may cause unexpected behavior while browsing the course.'), usage_key=_remove_version_info(seq_usage_key), )
def _make_not_bubbled_up_error(seq_usage_key, seq_group_access, user_partition_id, group_ids): return ContentErrorData( message=( f'<{seq_usage_key.block_type}> with url_name="{seq_usage_key.block_id}" ' f'has children with only group_ids {group_ids} for user_partition_id ' f'{user_partition_id}, but its own group_access setting is ' f'{seq_group_access}, which takes precedence. This is permitted, ' f'but probably not intended, since it means that the content is ' f'effectively unusable by anyone except staff.' ), usage_key=_remove_version_info(seq_usage_key), )
def _error_for_not_section(not_section): """ ContentErrorData when we run into a child of <course> that's not a Section. Has to be phrased in a way that makes sense to course teams. """ return ContentErrorData( message=( f'<course> contains a <{not_section.location.block_type}> tag with ' f'url_name="{not_section.location.block_id}" and ' f'display_name="{getattr(not_section, "display_name", "")}". ' f'Expected <chapter> tag instead.'), usage_key=_remove_version_info(not_section.location), )
def _error_for_not_sequence(section, not_sequence): """ ContentErrorData when we run into a child of Section that's not a Sequence. Has to be phrased in a way that makes sense to course teams. """ return ContentErrorData( message=( f'<chapter> with url_name="{section.location.block_id}" and ' f'display_name="{section.display_name}" contains a ' f'<{not_sequence.location.block_type}> tag with ' f'url_name="{not_sequence.location.block_id}" and ' f'display_name="{getattr(not_sequence, "display_name", "")}". ' f'Expected a <sequential> tag.'), usage_key=_remove_version_info(not_sequence.location), )
def _error_for_duplicate_child(section, duplicate_child, original_section): """ ContentErrorData when we run into a child of Section that's defined in a previous section. Has to be phrased in a way that makes sense to course teams. """ return ContentErrorData( message=( f'<chapter> with url_name="{section.location.block_id}" and ' f'display_name="{section.display_name}" contains a ' f'<{duplicate_child.location.block_type}> tag with ' f'url_name="{duplicate_child.location.block_id}" and ' f'display_name="{getattr(duplicate_child, "display_name", "")}" ' f'that is defined in another section with ' f'url_name="{original_section.location.block_id}" and ' f'display_name="{original_section.display_name}". Expected a ' f'unique <sequential> tag instead.'), usage_key=_remove_version_info(duplicate_child.location), )