def is_commentable_cohorted(course_key, commentable_id): """ Args: course_key: CourseKey commentable_id: string Returns: Bool: is this commentable cohorted? Raises: Http404 if the course doesn't exist. """ course = courses.get_course_by_id(course_key) course_cohort_settings = get_course_cohort_settings(course_key) if not course_cohort_settings.is_cohorted or get_team(commentable_id): # this is the easy case :) ans = False elif ( commentable_id in course.top_level_discussion_topic_ids or course_cohort_settings.always_cohort_inline_discussions is False ): # top level discussions have to be manually configured as cohorted # (default is not). # Same thing for inline discussions if the default is explicitly set to False in settings ans = commentable_id in course_cohort_settings.cohorted_discussions else: # inline discussions are cohorted by default ans = True log.debug(u"is_commentable_cohorted(%s, %s) = {%s}", course_key, commentable_id, ans) return ans
def is_commentable_cohorted(course_key, commentable_id): """ Args: course_key: CourseKey commentable_id: string Returns: Bool: is this commentable cohorted? Raises: Http404 if the course doesn't exist. """ course = courses.get_course_by_id(course_key) course_cohort_settings = get_course_cohort_settings(course_key) if not course_cohort_settings.is_cohorted or get_team(commentable_id): # this is the easy case :) ans = False elif (commentable_id in course.top_level_discussion_topic_ids or course_cohort_settings.always_cohort_inline_discussions is False): # top level discussions have to be manually configured as cohorted # (default is not). # Same thing for inline discussions if the default is explicitly set to False in settings ans = commentable_id in course_cohort_settings.cohorted_discussions else: # inline discussions are cohorted by default ans = True log.debug(u"is_commentable_cohorted(%s, %s) = {%s}", course_key, commentable_id, ans) return ans
def dump_one(self, *args, **options): if not args: raise CommandError("Course id not specified") if len(args) > 2: raise CommandError("Only one course id may be specified") raw_course_key = args[0] if len(args) == 1: output_file_location = self.get_default_file_location(raw_course_key) else: output_file_location = args[1] try: course_key = CourseKey.from_string(raw_course_key) except InvalidKeyError: course_key = SlashSeparatedCourseKey.from_deprecated_string(raw_course_key) course = get_course(course_key) if not course: raise CommandError("Invalid course id: {}".format(course_key)) target_discussion_ids = None if options.get(self.COHORTED_ONLY_PARAMETER, False): cohorted_discussions = get_course_cohort_settings(course_key).cohorted_discussions if not cohorted_discussions: raise MissingCohortedConfigCommandError( "Only cohorted discussions are marked for export, " "but no cohorted discussions found for the course") else: target_discussion_ids = cohorted_discussions raw_end_date = options.get(self.END_DATE_PARAMETER, None) end_date = dateutil.parser.parse(raw_end_date) if raw_end_date else None data = Extractor().extract( course_key, end_date=end_date, thread_type=(options.get(self.THREAD_TYPE_PARAMETER, None)), thread_ids=target_discussion_ids, ) filter_str = self._get_filter_string_representation(options) self.stdout.write("Writing social stats ({}) to {}\n".format(filter_str, output_file_location)) with open(output_file_location, 'wb') as output_stream: Exporter(output_stream).export(data)
def val_cohorts(self): """Проверка наличия в курсе когорт, для каждой вывод их численности либо сообщение об их отсутствии""" course = self.course cohorts = get_course_cohorts(course) names = [getattr(x, "name") for x in cohorts] users = [getattr(x, "users").all() for x in cohorts] report = [] cohort_strs = [] for num, x in enumerate(names): cohort_strs.append([x, str(len(users[num]))]) is_cohorted = get_course_cohort_settings(self.course_key).is_cohorted if not is_cohorted: cohort_strs = [] report.append(_("Cohorts are disabled")) result = Report(name=self.scenarios_names["cohorts"], head=[_(" Cohorts "), _("Population")], body=cohort_strs, warnings=report, ) return result
def get_discussion_category_map(course, user, cohorted_if_in_list=False, exclude_unstarted=True): """ Transform the list of this course's discussion modules into a recursive dictionary structure. This is used to render the discussion category map in the discussion tab sidebar for a given user. Args: course: Course for which to get the ids. user: User to check for access. cohorted_if_in_list (bool): If True, inline topics are marked is_cohorted only if they are in course_cohort_settings.discussion_topics. Example: >>> example = { >>> "entries": { >>> "General": { >>> "sort_key": "General", >>> "is_cohorted": True, >>> "id": "i4x-edx-eiorguegnru-course-foobarbaz" >>> } >>> }, >>> "children": ["General", "Getting Started"], >>> "subcategories": { >>> "Getting Started": { >>> "subcategories": {}, >>> "children": [ >>> "Working with Videos", >>> "Videos on edX" >>> ], >>> "entries": { >>> "Working with Videos": { >>> "sort_key": None, >>> "is_cohorted": False, >>> "id": "d9f970a42067413cbb633f81cfb12604" >>> }, >>> "Videos on edX": { >>> "sort_key": None, >>> "is_cohorted": False, >>> "id": "98d8feb5971041a085512ae22b398613" >>> } >>> } >>> } >>> } >>> } """ unexpanded_category_map = defaultdict(list) modules = get_accessible_discussion_modules(course, user) course_cohort_settings = get_course_cohort_settings(course.id) for module in modules: id = module.discussion_id title = module.discussion_target sort_key = module.sort_key category = " / ".join([x.strip() for x in module.discussion_category.split("/")]) # Handle case where module.start is None entry_start_date = module.start if module.start else datetime.max.replace(tzinfo=pytz.UTC) unexpanded_category_map[category].append({"title": title, "id": id, "sort_key": sort_key, "start_date": entry_start_date}) category_map = {"entries": defaultdict(dict), "subcategories": defaultdict(dict)} for category_path, entries in unexpanded_category_map.items(): node = category_map["subcategories"] path = [x.strip() for x in category_path.split("/")] # Find the earliest start date for the entries in this category category_start_date = None for entry in entries: if category_start_date is None or entry["start_date"] < category_start_date: category_start_date = entry["start_date"] for level in path[:-1]: if level not in node: node[level] = {"subcategories": defaultdict(dict), "entries": defaultdict(dict), "sort_key": level, "start_date": category_start_date} else: if node[level]["start_date"] > category_start_date: node[level]["start_date"] = category_start_date node = node[level]["subcategories"] level = path[-1] if level not in node: node[level] = {"subcategories": defaultdict(dict), "entries": defaultdict(dict), "sort_key": level, "start_date": category_start_date} else: if node[level]["start_date"] > category_start_date: node[level]["start_date"] = category_start_date always_cohort_inline_discussions = ( # pylint: disable=invalid-name not cohorted_if_in_list and course_cohort_settings.always_cohort_inline_discussions ) dupe_counters = defaultdict(lambda: 0) # counts the number of times we see each title for entry in entries: is_entry_cohorted = ( course_cohort_settings.is_cohorted and ( always_cohort_inline_discussions or entry["id"] in course_cohort_settings.cohorted_discussions ) ) title = entry["title"] if node[level]["entries"][title]: # If we've already seen this title, append an incrementing number to disambiguate # the category from other categores sharing the same title in the course discussion UI. dupe_counters[title] += 1 title = u"{title} ({counter})".format(title=title, counter=dupe_counters[title]) node[level]["entries"][title] = {"id": entry["id"], "sort_key": entry["sort_key"], "start_date": entry["start_date"], "is_cohorted": is_entry_cohorted} # TODO. BUG! : course location is not unique across multiple course runs! # (I think Kevin already noticed this) Need to send course_id with requests, store it # in the backend. for topic, entry in course.discussion_topics.items(): category_map['entries'][topic] = { "id": entry["id"], "sort_key": entry.get("sort_key", topic), "start_date": datetime.now(UTC()), "is_cohorted": (course_cohort_settings.is_cohorted and entry["id"] in course_cohort_settings.cohorted_discussions) } _sort_map_entries(category_map, course.discussion_sort_alpha) return _filter_unstarted_categories(category_map) if exclude_unstarted else category_map
def get_discussion_category_map(course, user, cohorted_if_in_list=False, exclude_unstarted=True): """ Transform the list of this course's discussion modules into a recursive dictionary structure. This is used to render the discussion category map in the discussion tab sidebar for a given user. Args: course: Course for which to get the ids. user: User to check for access. cohorted_if_in_list (bool): If True, inline topics are marked is_cohorted only if they are in course_cohort_settings.discussion_topics. Example: >>> example = { >>> "entries": { >>> "General": { >>> "sort_key": "General", >>> "is_cohorted": True, >>> "id": "i4x-edx-eiorguegnru-course-foobarbaz" >>> } >>> }, >>> "children": ["General", "Getting Started"], >>> "subcategories": { >>> "Getting Started": { >>> "subcategories": {}, >>> "children": [ >>> "Working with Videos", >>> "Videos on edX" >>> ], >>> "entries": { >>> "Working with Videos": { >>> "sort_key": None, >>> "is_cohorted": False, >>> "id": "d9f970a42067413cbb633f81cfb12604" >>> }, >>> "Videos on edX": { >>> "sort_key": None, >>> "is_cohorted": False, >>> "id": "98d8feb5971041a085512ae22b398613" >>> } >>> } >>> } >>> } >>> } """ unexpanded_category_map = defaultdict(list) modules = get_accessible_discussion_modules(course, user) course_cohort_settings = get_course_cohort_settings(course.id) for module in modules: id = module.discussion_id title = module.discussion_target sort_key = module.sort_key category = " / ".join( [x.strip() for x in module.discussion_category.split("/")]) # Handle case where module.start is None entry_start_date = module.start if module.start else datetime.max.replace( tzinfo=pytz.UTC) unexpanded_category_map[category].append({ "title": title, "id": id, "sort_key": sort_key, "start_date": entry_start_date }) category_map = { "entries": defaultdict(dict), "subcategories": defaultdict(dict) } for category_path, entries in unexpanded_category_map.items(): node = category_map["subcategories"] path = [x.strip() for x in category_path.split("/")] # Find the earliest start date for the entries in this category category_start_date = None for entry in entries: if category_start_date is None or entry[ "start_date"] < category_start_date: category_start_date = entry["start_date"] for level in path[:-1]: if level not in node: node[level] = { "subcategories": defaultdict(dict), "entries": defaultdict(dict), "sort_key": level, "start_date": category_start_date } else: if node[level]["start_date"] > category_start_date: node[level]["start_date"] = category_start_date node = node[level]["subcategories"] level = path[-1] if level not in node: node[level] = { "subcategories": defaultdict(dict), "entries": defaultdict(dict), "sort_key": level, "start_date": category_start_date } else: if node[level]["start_date"] > category_start_date: node[level]["start_date"] = category_start_date always_cohort_inline_discussions = ( # pylint: disable=invalid-name not cohorted_if_in_list and course_cohort_settings.always_cohort_inline_discussions) dupe_counters = defaultdict( lambda: 0) # counts the number of times we see each title for entry in entries: is_entry_cohorted = ( course_cohort_settings.is_cohorted and (always_cohort_inline_discussions or entry["id"] in course_cohort_settings.cohorted_discussions)) title = entry["title"] if node[level]["entries"][title]: # If we've already seen this title, append an incrementing number to disambiguate # the category from other categores sharing the same title in the course discussion UI. dupe_counters[title] += 1 title = u"{title} ({counter})".format( title=title, counter=dupe_counters[title]) node[level]["entries"][title] = { "id": entry["id"], "sort_key": entry["sort_key"], "start_date": entry["start_date"], "is_cohorted": is_entry_cohorted } # TODO. BUG! : course location is not unique across multiple course runs! # (I think Kevin already noticed this) Need to send course_id with requests, store it # in the backend. for topic, entry in course.discussion_topics.items(): category_map['entries'][topic] = { "id": entry["id"], "sort_key": entry.get("sort_key", topic), "start_date": datetime.now(UTC()), "is_cohorted": (course_cohort_settings.is_cohorted and entry["id"] in course_cohort_settings.cohorted_discussions) } _sort_map_entries(category_map, course.discussion_sort_alpha) return _filter_unstarted_categories( category_map) if exclude_unstarted else category_map