Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
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)
Ejemplo n.º 4
0
 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
Ejemplo n.º 5
0
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
Ejemplo n.º 6
0
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