def subtopics(store, folders, folder_id, subfolder_id, ann_id=None):
    '''Yields an unordered generator of subtopics in a subfolder.

    Each item of the generator is a 4-tuple of ``content_id``,
    ``subtopic_id``, ``subtopic_type`` and ``data``. Subtopic type
    is one of the following Unicode strings: ``text``, ``image``
    or ``manual``. The type of ``data`` is dependent on the
    subtopic type. For ``image``, ``data`` is a ``(unicode, str)``,
    where the first element is the URL and the second element is
    the binary image data. For all other types, ``data`` is a
    ``unicode`` string.

    :param str folder_id: Folder id
    :param str subfolder_id: Subfolder id
    :param str ann_id: Username
    :rtype: generator of
            ``(content_id, subtopic_id, url, subtopic_type, data)``
    '''
    # This code will be changed soon. In essence, it implements the
    # convention established in SortingDesk for storing subtopic data.
    # Currently, subtopic data is stored in the FC that the data (i.e.,
    # image or snippet) came from. This is bad because it causes pretty
    # severe race conditions.
    #
    # Our current plan is to put each subtopic datum in its own FC. It will
    # require this code to make more FC fetches, but we should be able to
    # do it with one `store.get_many` call.
    items = folders.grouped_items(folder_id, subfolder_id, ann_id=ann_id)
    fcs = dict([(cid, fc) for cid, fc in store.get_many(items.keys())])
    for cid, subids in items.iteritems():
        fc = fcs[cid]
        for subid in subids:
            try:
                data = typed_subtopic_data(fc, subid)
            except __HOLE__:
                # We have a dangling label folks!
                continue
            yield cid, subid, fc['meta_url'], subtopic_type(subid), data
dataset/ETHPy150Open dossier/dossier.models/dossier/models/subtopic.py/subtopics