# Buggy code
def get_announcements(self, **kwargs):
    """
        List announcements.

        :calls: `GET /api/v1/announcements \
        <https://canvas.instructure.com/doc/api/announcements.html#method.announcements_api.index>`_

        :rtype: :class:`canvasapi.paginated_list.PaginatedList` of
                :class:`canvasapi.discussion_topic.DiscussionTopic`
        """
    from canvasapi.discussion_topic import DiscussionTopic

    return PaginatedList(
        DiscussionTopic,
        self.__requester,
        "GET",
        "announcements",
        _kwargs=combine_kwargs(**kwargs),
    )


# Traceback (ValueError)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-15-667b0a4b45f2> in <module>
2 announcements = canvas.get_announcements(context_codes=['course_{}'.format(course_id)])
3 a = announcements[0]
----> 4 a.update()

~/opt/anaconda3/lib/python3.7/site-packages/canvasapi/discussion_topic.py in update(self, **kwargs)
309             "PUT",
310             "{}s/{}/discussion_topics/{}".format(
--> 311                 self._parent_type, self._parent_id, self.id
312             ),
313             _kwargs=combine_kwargs(**kwargs),

~/opt/anaconda3/lib/python3.7/site-packages/canvasapi/canvas_object.py in __getattribute__(self, name)
15
16     def __getattribute__(self, name):
---> 17         return super(CanvasObject, self).__getattribute__(name)
18
19     def __init__(self, requester, attributes):

~/opt/anaconda3/lib/python3.7/site-packages/canvasapi/discussion_topic.py in _parent_type(self)
34             return "group"
35         else:
---> 36             raise ValueError("Discussion Topic does not have a course_id or group_id")
37
38     def delete(self, **kwargs):

ValueError: Discussion Topic does not have a course_id or group_id

# Fixed code
def get_announcements(self, courses, **kwargs):
    """
        List announcements.

        :calls: `GET /api/v1/announcements \
        <https://canvas.instructure.com/doc/api/announcements.html#method.announcements_api.index>`_

        :param courses: Course ID(s) or <Course> objects to request announcements from.
        :type courses: list

        :rtype: :class:`canvasapi.paginated_list.PaginatedList` of
                :class:`canvasapi.discussion_topic.DiscussionTopic`
        """
    from canvasapi.discussion_topic import DiscussionTopic

    if type(courses) is not list or len(courses) == 0:
        raise RequiredFieldMissing("Course IDs need to be passed as a list")

    # The type of object in `courses` is taken care of by obj_or_id, extracting the couse
    # ID from a <Course> object or by returning plain strings.
    course_ids = [obj_or_id(course_id, "course_id", (Course,)) for course_id in courses]

    # Set the **kwargs object vaue so it can be combined with others passed by the user.
    kwargs["context_codes"] = [f"course_{course_id}" for course_id in course_ids]

    return PaginatedList(
        DiscussionTopic,
        self.__requester,
        "GET",
        "announcements",
        context_codes=course_ids,
        _kwargs=combine_kwargs(**kwargs),
    )