def topic_context(topic): """ Given a topic node, create all context related to showing that topic in a template. """ videos = topic_tools.get_videos(topic) exercises = topic_tools.get_exercises(topic) topics = topic_tools.get_live_topics(topic) # Get video counts if they'll be used, on-demand only. # # Check in this order so that the initial counts are always updated if video_counts_need_update() or not 'nvideos_local' in topic: (topic,_,_) = get_video_counts(topic=topic, videos_path=settings.CONTENT_ROOT) my_topics = [dict((k, t[k]) for k in ('title', 'path', 'nvideos_local', 'nvideos_known')) for t in topics] context = { "topic": topic, "title": topic["title"], "description": re.sub(r'<[^>]*?>', '', topic["description"] or ""), "videos": videos, "exercises": exercises, "topics": my_topics, "backup_vids_available": bool(settings.BACKUP_VIDEO_SOURCE), } return context
def get_video_counts(topic, videos_path=settings.CONTENT_ROOT, force=False): """ Uses the (json) topic tree to query the django database for which video files exist Returns the original topic dictionary, with two properties added to each NON-LEAF node: * nvideos_known: The # of videos in and under that node, that are known (i.e. in the Khan Academy library) * nvideos_local: The # of vidoes in and under that node, that were actually downloaded and available locally And the following property for leaf nodes: * on_disk Input Parameters: * videos_path: the path to video files """ if not force and "nvideos_local" in topic: return (topic, topic["nvideos_local"], topic["nvideos_known"], False) nvideos_local = 0 nvideos_known = 0 # Can't deal with leaves assert "children" in topic, "Should not be calling this function on leaves; it's inefficient!" # Only look for videos if there are more branches if len(topic["children"]) == 0: logging.debug("no children: %s" % topic["path"]) elif len(topic["children"]) > 0: # RECURSIVE CALL: # The children have children, let them figure things out themselves # $ASSUMPTION: if first child is a branch, THEY'RE ALL BRANCHES. # if first child is a leaf, THEY'RE ALL LEAVES if "children" in topic["children"][0]: for child in topic["children"]: if not force and "nvideos_local" in child: continue (child, _, _, _) = get_video_counts(topic=child, videos_path=videos_path) nvideos_local += child["nvideos_local"] nvideos_known += child["nvideos_known"] # BASE CASE: # All my children are leaves, so we'll query here (a bit more efficient than 1 query per leaf) else: videos = get_videos(topic) for video in videos: if force or "urls" not in video: stamp_urls_on_video(video) nvideos_local += int(bool( video["urls"])) # add 1 if video["on_disk"] nvideos_known = len(videos) changed = topic.get("nvideos_local", -1) != nvideos_local changed = changed or topic.get("nvideos_known", -1) != nvideos_known topic["nvideos_local"] = nvideos_local topic["nvideos_known"] = nvideos_known topic["available"] = bool(nvideos_local) or bool( settings.BACKUP_VIDEO_SOURCE) return (topic, nvideos_local, nvideos_known, changed)
def stamp_availability_on_topic(topic, videos_path=settings.CONTENT_ROOT, force=True, stamp_urls=True): """ Uses the (json) topic tree to query the django database for which video files exist Returns the original topic dictionary, with two properties added to each NON-LEAF node: * nvideos_known: The # of videos in and under that node, that are known (i.e. in the Khan Academy library) * nvideos_local: The # of vidoes in and under that node, that were actually downloaded and available locally And the following property for leaf nodes: * on_disk Input Parameters: * videos_path: the path to video files """ if not force and "nvideos_local" in topic: return (topic, topic["nvideos_local"], topic["nvideos_known"], False) nvideos_local = 0 nvideos_known = 0 # Can't deal with leaves assert "children" in topic, "Should not be calling this function on leaves; it's inefficient!" # Only look for videos if there are more branches if len(topic["children"]) == 0: logging.debug("no children: %s" % topic["path"]) elif len(topic["children"]) > 0: # RECURSIVE CALL: # The children have children, let them figure things out themselves # $ASSUMPTION: if first child is a branch, THEY'RE ALL BRANCHES. # if first child is a leaf, THEY'RE ALL LEAVES if "children" in topic["children"][0]: for child in topic["children"]: if not force and "nvideos_local" in child: continue stamp_availability_on_topic(topic=child, videos_path=videos_path, force=force, stamp_urls=stamp_urls) nvideos_local += child["nvideos_local"] nvideos_known += child["nvideos_known"] # BASE CASE: # All my children are leaves, so we'll query here (a bit more efficient than 1 query per leaf) else: videos = get_videos(topic) for video in videos: if force or "availability" not in video: stamp_availability_on_video(video, force=force, stamp_urls=stamp_urls) nvideos_local += int(video["on_disk"]) nvideos_known = len(videos) changed = "nvideos_local" in topic and topic["nvideos_local"] != nvideos_local changed = changed or ("nvideos_known" in topic and topic["nvideos_known"] != nvideos_known) topic["nvideos_local"] = nvideos_local topic["nvideos_known"] = nvideos_known topic["available"] = bool(nvideos_local) or bool(settings.BACKUP_VIDEO_SOURCE) return (topic, nvideos_local, nvideos_known, changed)
def get_video_counts(topic, videos_path, force=False): """ Uses the (json) topic tree to query the django database for which video files exist Returns the original topic dictionary, with two properties added to each NON-LEAF node: * nvideos_known: The # of videos in and under that node, that are known (i.e. in the Khan Academy library) * nvideos_local: The # of vidoes in and under that node, that were actually downloaded and available locally And the following property for leaf nodes: * on_disk Input Parameters: * videos_path: the path to video files """ nvideos_local = 0 nvideos_known = 0 # Can't deal with leaves assert "children" in topic, "Should not be calling this function on leaves; it's inefficient!" # Only look for videos if there are more branches if len(topic["children"]) == 0: logging.debug("no children: %s" % topic["path"]) elif len(topic["children"]) > 0: # RECURSIVE CALL: # The children have children, let them figure things out themselves # $ASSUMPTION: if first child is a branch, THEY'RE ALL BRANCHES. # if first child is a leaf, THEY'RE ALL LEAVES if "children" in topic["children"][0]: for child in topic["children"]: (child, _, _) = get_video_counts(topic=child, videos_path=videos_path) nvideos_local += child["nvideos_local"] nvideos_known += child["nvideos_known"] # BASE CASE: # All my children are leaves, so we'll query here (a bit more efficient than 1 query per leaf) else: videos = get_videos(topic) if len(videos) > 0: for video in videos: # Mark all videos as not found video["on_disk"] = is_video_on_disk( video["youtube_id"], videos_path) nvideos_local += int( video["on_disk"]) # add 1 if video["on_disk"] nvideos_known = len(videos) topic["nvideos_local"] = nvideos_local topic["nvideos_known"] = nvideos_known return (topic, nvideos_local, nvideos_known)
def get_video_counts(topic, videos_path, force=False): """ Uses the (json) topic tree to query the django database for which video files exist Returns the original topic dictionary, with two properties added to each NON-LEAF node: * nvideos_known: The # of videos in and under that node, that are known (i.e. in the Khan Academy library) * nvideos_local: The # of vidoes in and under that node, that were actually downloaded and available locally And the following property for leaf nodes: * on_disk Input Parameters: * videos_path: the path to video files """ nvideos_local = 0 nvideos_known = 0 # Can't deal with leaves assert "children" in topic, "Should not be calling this function on leaves; it's inefficient!" # Only look for videos if there are more branches if len(topic["children"]) == 0: logging.debug("no children: %s" % topic["path"]) elif len(topic["children"]) > 0: # RECURSIVE CALL: # The children have children, let them figure things out themselves # $ASSUMPTION: if first child is a branch, THEY'RE ALL BRANCHES. # if first child is a leaf, THEY'RE ALL LEAVES if "children" in topic["children"][0]: for child in topic["children"]: (child, _, _) = get_video_counts(topic=child, videos_path=videos_path) nvideos_local += child["nvideos_local"] nvideos_known += child["nvideos_known"] # BASE CASE: # All my children are leaves, so we'll query here (a bit more efficient than 1 query per leaf) else: videos = get_videos(topic) if len(videos) > 0: for video in videos: # Mark all videos as not found video["on_disk"] = is_video_on_disk(video["youtube_id"], videos_path) nvideos_local += int(video["on_disk"]) # add 1 if video["on_disk"] nvideos_known = len(videos) topic["nvideos_local"] = nvideos_local topic["nvideos_known"] = nvideos_known return (topic, nvideos_local, nvideos_known)
def topic_context(topic): """ Given a topic node, create all context related to showing that topic in a template. """ videos = topic_tools.get_videos(topic) exercises = topic_tools.get_exercises(topic) topics = topic_tools.get_live_topics(topic) my_topics = [dict((k, t[k]) for k in ('title', 'path', 'nvideos_local', 'nvideos_known')) for t in topics] context = { "topic": topic, "title": topic["title"], "description": re.sub(r'<[^>]*?>', '', topic["description"] or ""), "videos": videos, "exercises": exercises, "topics": my_topics, "backup_vids_available": bool(settings.BACKUP_VIDEO_SOURCE), } return context
def topic_context(topic): """ Given a topic node, create all context related to showing that topic in a template. """ videos = topic_tools.get_videos(topic) exercises = topic_tools.get_exercises(topic) topics = topic_tools.get_live_topics(topic) my_topics = [dict((k, t[k]) for k in ('title', 'path', 'nvideos_local', 'nvideos_known')) for t in topics] exercises_path = os.path.join(settings.STATIC_ROOT, "js", "khan-exercises", "exercises") exercise_langs = dict([(exercise["id"], ["en"]) for exercise in exercises]) for lang_code in os.listdir(exercises_path): loc_path = os.path.join(exercises_path, lang_code) if not os.path.isdir(loc_path): continue for exercise in exercises: ex_path = os.path.join(loc_path, "%s.html" % exercise["id"]) if not os.path.exists(ex_path): continue exercise_langs[exercise["id"]].append(lang_code) context = { "topic": topic, "title": topic["title"], "description": re.sub(r'<[^>]*?>', '', topic["description"] or ""), "videos": videos, "exercises": exercises, "exercise_langs": exercise_langs, "topics": my_topics, "backup_vids_available": bool(settings.BACKUP_VIDEO_SOURCE), } return context