Skip to content

files_upload_v2 does not work with io.BytesIO file parameters #1292

@seratch

Description

@seratch

Is this type hint correct? I tried to pass in a io.BytesIO object here as the file as I thought IOBase covers that as well as a real file handle (e.g. from open("filename", "rb")) - but it failed with TypeError: object of type '_io.BytesIO' has no len() - len comes from _to_v2_file_upload_item I believe. So either the type hint is incorrect or the implementation of _to_v2_file_upload_item needs tweaking? You could probably just do something like this?

def _to_v2_file_upload_item(upload_file: Dict[str, Any]) -> Dict[str, Optional[Any]]:
    file = upload_file.get("file")
    content = upload_file.get("content")
    data: Optional[bytes] = None
    if file is not None:
        if isinstance(file, str):  # filepath
            with open(file.encode("utf-8", "ignore"), "rb") as readable:
                data = readable.read()
        elif isinstance(file, io.IOBase):
            # new stuff
            data = file.read()
            if isinstance(data, str):
                data = data.encode()
        elif isinstance(file, bytes):
            data = file
        else:
            raise SlackRequestError("The given file must be either a filepath as str or data as bytes/IOBase")
    elif content is not None:
        if isinstance(content, str):  # str content
            data = content.encode("utf-8")
        elif isinstance(content, bytes):
            data = content
        else:
            raise SlackRequestError("The given content given as str or as bytes")

    filename = upload_file.get("filename")
    if upload_file.get("filename") is None and isinstance(file, str):
        # use the local filename if filename is missing
        if upload_file.get("filename") is None:
            filename = file.split(os.path.sep)[-1]
        else:
            filename = "Uploaded file"

    title = upload_file.get("title", "Uploaded file")
    if data is None:
        raise SlackRequestError(f"File content not found for filename: {filename}, title: {title}")

    if title is None:
        title = filename  # to be consistent with files.upload API

    return {
        "filename": filename,
        "data": data,
        "length": len(data),
        "title": title,
        "alt_txt": upload_file.get("alt_txt"),
        "snippet_type": upload_file.get("snippet_type"),
    }

Originally posted by @Alex-ley-scrub in #1272 (comment)

Metadata

Metadata

Assignees

Labels

Version: 3xbugM-T: A confirmed bug report. Issues are confirmed when the reproduction steps are documentedweb-client

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions