Attach an attachment to an issue and returns a Resource for it.

        The client will *not* attempt to open or validate the attachment; it expects a file-like object to be ready
        for its use. The user is still responsible for tidying up (e.g., closing the file, killing the socket, etc.)

        :param issue: the issue to attach the attachment to
        :type issue: str
        :param attachment: file-like object to attach to the issue, also works if it is a string with the filename.
        :type attachment: BufferedReader
        :param filename: optional name for the attached file. If omitted, the file object's ``name`` attribute
            is used. If you acquired the file-like object by any other method than ``open()``, make sure
            that a name is specified in one way or the other.
        :type filename: str
        :rtype: Attachment

def add_attachment(self, issue, attachment, filename=None):
        """Attach an attachment to an issue and returns a Resource for it.

        The client will *not* attempt to open or validate the attachment; it expects a file-like object to be ready
        for its use. The user is still responsible for tidying up (e.g., closing the file, killing the socket, etc.)

        :param issue: the issue to attach the attachment to
        :type issue: str
        :param attachment: file-like object to attach to the issue, also works if it is a string with the filename.
        :type attachment: BufferedReader
        :param filename: optional name for the attached file. If omitted, the file object's ``name`` attribute
            is used. If you acquired the file-like object by any other method than ``open()``, make sure
            that a name is specified in one way or the other.
        :type filename: str
        :rtype: Attachment
        """
        if isinstance(attachment, string_types):
            attachment = open(attachment, "rb")
        if hasattr(attachment, 'read') and hasattr(attachment, 'mode') and attachment.mode != 'rb':
            logging.warning(
                "%s was not opened in 'rb' mode, attaching file may fail." % attachment.name)

        url = self._get_url('issue/' + str(issue) + '/attachments')

        fname = filename
        if not fname:
            fname = os.path.basename(attachment.name)

        if 'MultipartEncoder' not in globals():
            method = 'old'
            r = self._session.post(
                url,
                files={
                    'file': (fname, attachment, 'application/octet-stream')},
                headers=CaseInsensitiveDict({'content-type': None, 'X-Atlassian-Token': 'nocheck'}))
        else:
            method = 'MultipartEncoder'

            def file_stream():
                """Returns files stream of attachment.

                :rtype: MultipartEncoder
                """
                return MultipartEncoder(
                    fields={
                        'file': (fname, attachment, 'application/octet-stream')})
            m = file_stream()
            r = self._session.post(
                url, data=m, headers=CaseInsensitiveDict({'content-type': m.content_type, 'X-Atlassian-Token': 'nocheck'}), retry_data=file_stream)

        js = json_loads(r)
        if not js or not isinstance(js, collections.Iterable):
            raise JIRAError("Unable to parse JSON: %s" % js)
        attachment = Attachment(self._options, self._session, js[0])
        if attachment.size == 0:
            raise JIRAError("Added empty attachment via %s method?!: r: %s\nattachment: %s" % (method, r, attachment))
        return attachment