docs: 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