Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix sanic adapter casting files to io.BytesIO #3751

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

Maypher
Copy link

@Maypher Maypher commented Jan 10, 2025

The current implementation of strawberry.sanic.utils.convert_request_to_files_dict casts uploaded files to io.BytesIO, making it return a type that doesn't coincide with the docs. This commit removes this casting and makes the function work in accordance with the docs.

Description

Changed files_dict[field_name] = BytesIO(file_list[0].body) to files_dict[field_name] = file_list[0]

Types of Changes

  • Core
  • Bugfix
  • New feature
  • Enhancement/optimization
  • Documentation

Issues Fixed or Closed by This PR

Fix #3750

Checklist

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • I have tested the changes and verified that they work and don't break anything (as well as I can manage).

Summary by Sourcery

Bug Fixes:

  • Uploaded files are now correctly handled as Sanic File objects instead of being cast to io.BytesIO.

io.BytesIO which is the filetype used by AIOHTTP. This commit fixes this
issue by directly assigning the file instead of casting it.
Copy link
Contributor

sourcery-ai bot commented Jan 10, 2025

Reviewer's Guide by Sourcery

This PR fixes a bug in the strawberry.sanic.utils.convert_request_to_files_dict function where uploaded files were incorrectly cast to io.BytesIO. The change ensures the function returns the correct sanic.request.File type, aligning it with the documentation.

Sequence diagram for Sanic file upload handling before and after fix

sequenceDiagram
    participant Client
    participant SanicServer
    participant FileHandler

    Note over Client,FileHandler: Before Fix
    Client->>SanicServer: Upload file
    SanicServer->>FileHandler: convert_request_to_files_dict()
    FileHandler->>FileHandler: Convert to BytesIO
    FileHandler-->>SanicServer: Return BytesIO object

    Note over Client,FileHandler: After Fix
    Client->>SanicServer: Upload file
    SanicServer->>FileHandler: convert_request_to_files_dict()
    FileHandler-->>SanicServer: Return original Sanic File object
Loading

Class diagram showing the file handling type changes

classDiagram
    class Request {
        +files: dict
    }

    class FileHandler {
        +convert_request_to_files_dict(request: Request) dict
    }

    class File {
        +body: bytes
        +name: str
        +type: str
    }

    note for FileHandler "Changed return type from\ndict[str, BytesIO] to\ndict[str, File]"

    Request -- FileHandler
    FileHandler -- File
Loading

File-Level Changes

Change Details Files
Removed the casting of uploaded files to io.BytesIO.
  • Changed files_dict[field_name] = BytesIO(file_list[0].body) to files_dict[field_name] = file_list[0]
strawberry/sanic/utils.py
Added tests to verify the fix and ensure the function behaves as expected.
  • Created a new test file test_file_upload.py with tests covering the file upload functionality.
  • Added a test case to check that files are correctly converted to sanic.request.File objects.
  • Added a test case to verify that the GraphQL API handles file uploads correctly end-to-end.
  • Added a test case to verify that the file name is correctly returned after the upload process is completed
tests/sanic/test_file_upload.py
Updated the documentation to reflect the change.
  • Added a new release note in RELEASE.md to document the bug fix and the change in the returned file type
RELEASE.md

Possibly linked issues

  • #0: The PR fixes the bug where uploaded files were cast to io.BytesIO instead of sanic.request.File.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time. You can also use
    this command to specify where the summary should be inserted.

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @Maypher - I've reviewed your changes and they look great!

Here's what I looked at during the review
  • 🟡 General issues: 2 issues found
  • 🟢 Security: all looks good
  • 🟢 Testing: all looks good
  • 🟢 Complexity: all looks good
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@@ -29,12 +28,12 @@ def convert_request_to_files_dict(request: Request) -> dict[str, Any]:
if not request_files:
return {}

files_dict: dict[str, Union[BytesIO, list[BytesIO]]] = {}
files_dict: dict[str, Union[File, list[File]]] = {}

for field_name, file_list in request_files.items():
assert len(file_list) == 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: Consider handling multiple files per field name instead of asserting there will be exactly one

The assertion could cause server crashes if multiple files are uploaded with the same field name. Consider returning a list of File objects when multiple files are present, matching the type hint Union[File, list[File]].

RELEASE.md Outdated
Release type: patch

Fix bug where files would be converted into io.BytesIO when using the sanic GraphQLView
instead of using the sanic File type
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Check casing and specific name for "sanic File type"

Should it be "Sanic File", "Sanic file type", or something more specific? Referencing the Sanic documentation might help.

@botberry
Copy link
Member

Thanks for adding the RELEASE.md file!

Here's a preview of the changelog:


Fix bug where files would be converted into io.BytesIO when using the sanic GraphQLView
instead of using the sanic File type

Here's the tweet text:

🆕 Release (next) is out! Thanks to Maypher for the PR 👏

Get it here 👉 https://strawberry.rocks/release/(next)

@botberry
Copy link
Member

Thanks for adding the RELEASE.md file!

Here's a preview of the changelog:


Fix bug where files would be converted into io.BytesIO when using the sanic GraphQLView
instead of using the sanic File type

Here's the tweet text:

🆕 Release (next) is out! Thanks to Maypher for the PR 👏

Get it here 👉 https://strawberry.rocks/release/(next)

Copy link
Member

@patrick91 patrick91 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great, I might spend a bit of time moving the tests to the http tests, so we have one test for all integrations 😊

Copy link
Member

@bellini666 bellini666 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM :)

Will leave final review to @patrick91

Comment on lines +1 to +4
Release type: patch

Fix bug where files would be converted into io.BytesIO when using the sanic GraphQLView
instead of using the sanic File type
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thought: although a bug, someone using it might have gotten already used to it being BytesIO, so maybe we should mark this as a minor and mention that anyone relying on old behavior should adjust their code?

What do you think @patrick91 ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Upload type not being correctly converted into Sanic File type at runtime
4 participants