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

Add MIME content type info to File #143

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

jhnstrk
Copy link
Contributor

@jhnstrk jhnstrk commented Apr 30, 2024

Adds MIME type information as File.content_type as requested in issue #58.

Tests have been updated and a case-sensitive header issue was fixed too.

The part headers are also exposed as a dict, with keys as strings, lower-cased as File.headers.

multipart/multipart.py Outdated Show resolved Hide resolved
multipart/multipart.py Outdated Show resolved Hide resolved
multipart/multipart.py Outdated Show resolved Hide resolved
multipart/multipart.py Outdated Show resolved Hide resolved
multipart/multipart.py Outdated Show resolved Hide resolved
Makes all headers lower case, fixing case sensitivity issues.
Exposes jheaders property in Files and Fields.
@@ -68,12 +68,14 @@ def finalize(self) -> None: ...
def close(self) -> None: ...

class FieldProtocol(_FormProtocol, Protocol):
def __init__(self, name: bytes | None) -> None: ...
def __init__(self, name: bytes, content_type: str | None = None) -> None: ...
Copy link
Owner

Choose a reason for hiding this comment

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

Is it needed on Field?

Copy link
Contributor Author

@jhnstrk jhnstrk Dec 11, 2024

Choose a reason for hiding this comment

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

Yes, but not frequently used. Examples:

Copy link
Owner

Choose a reason for hiding this comment

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

Specifying a charset for a field

This is enough to convince me. Thanks.

python_multipart/multipart.py Outdated Show resolved Hide resolved
python_multipart/multipart.py Outdated Show resolved Hide resolved
python_multipart/multipart.py Outdated Show resolved Hide resolved
disp, options = parse_options_header(content_disp)

# Get the field and filename.
field_name = options.get(b"name")
field_name = options.get(b"name", b"")
Copy link
Owner

Choose a reason for hiding this comment

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

Is this needed? Isn't the field_name supposed to always be present?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added this for typing. Without it, we'll need to raise or assert it's not None. Which makes sense actually.
Will probably need a test to cover it. too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed the default value and added a check for None.

@@ -1656,7 +1678,7 @@ def on_header_value(data: bytes, start: int, end: int) -> None:
header_value.append(data[start:end])

def on_header_end() -> None:
headers[b"".join(header_name)] = b"".join(header_value)
headers[b"".join(header_name).decode().lower()] = b"".join(header_value)
Copy link
Owner

Choose a reason for hiding this comment

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

Do we need to decode?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think the headers dict is easier to use if the keys are strings rather than bytes, so I used decode to do the transformation. The string is guaranteed to be valid since it can only contain a subset of ASCII characters (it's filtered as it's built). Can be bytes if you prefer, in which case decode isn't needed.

Copy link
Owner

Choose a reason for hiding this comment

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

Does it need to be in this PR?

"""

def __init__(self, name: bytes | None) -> None:
def __init__(self, name: bytes, content_type: str | None = None) -> None:
Copy link
Owner

Choose a reason for hiding this comment

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

Why did the name type changed here? Now we have a mismatch between this and the File.field_name. 🤔

Can we revert this bit?

@@ -1540,7 +1562,7 @@ def __init__(

def on_start() -> None:
nonlocal file
file = FileClass(file_name, None, config=cast("FileConfig", self.config))
file = FileClass(file_name, b"", config=cast("FileConfig", self.config))
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
file = FileClass(file_name, b"", config=cast("FileConfig", self.config))
file = FileClass(file_name, config=cast("FileConfig", self.config))

@@ -1656,7 +1678,7 @@ def on_header_value(data: bytes, start: int, end: int) -> None:
header_value.append(data[start:end])

def on_header_end() -> None:
headers[b"".join(header_name)] = b"".join(header_value)
headers[b"".join(header_name).decode().lower()] = b"".join(header_value)
Copy link
Owner

Choose a reason for hiding this comment

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

Does it need to be in this PR?

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

Successfully merging this pull request may close these issues.

2 participants