Skip to content

jwcrypto: Fix export_to_pem password argument #14037

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

Merged
merged 2 commits into from
May 13, 2025

Conversation

mazei513
Copy link
Contributor

No description provided.

This comment has been minimized.

@@ -201,7 +201,7 @@ class JWK(dict[str, Any]):
),
) -> None: ...
def import_from_pem(self, data: bytes, password: bytes | None = None, kid: str | None = None) -> None: ...
def export_to_pem(self, private_key: bool = False, password: bool = False) -> bytes: ...
def export_to_pem(self, private_key: bool = False, password: Literal[False] | bytes | None = False) -> bytes: ...
Copy link
Collaborator

@srittau srittau May 13, 2025

Choose a reason for hiding this comment

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

From what I can see, password is really a required argument, and False is just a sentinel, since writing def export_to_pem(self, private_key=False, password): is illegal syntax. In this case, I think we can do better in the stubs using overloads:

Suggested change
def export_to_pem(self, private_key: bool = False, password: Literal[False] | bytes | None = False) -> bytes: ...
@overload
def export_to_pem(self, private_key: bool, password: bytes | None) -> bytes: ...
@overload
def export_to_pem(self, private_key: bool = False, *, password: bytes | None) -> bytes: ...

(This might make stubtest unhappy, im which case we need to add an entry to stubs/jwcrypto/@tests/stubtest_allowlist.txt.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My understanding is password is only required if private_key is True. Would this be fine?

    @overload
    def export_to_pem(self, private_key: Literal[False] = False, password: Literal[False] | bytes | None = False) -> bytes: ...
    @overload
    def export_to_pem(self, private_key: Literal[True], password: bytes | None) -> bytes: ...

Copy link
Collaborator

Choose a reason for hiding this comment

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

Oops, yes you are right. Your overload looks fine, here are two other alternatives:

    from _typeshed import Unused

    @overload
    def export_to_pem(self, private_key: Literal[False] = False, password: Unused = False) -> bytes: ...
    @overload
    def export_to_pem(self, private_key: Literal[True], password: bytes | None) -> bytes: ...

Unused is a type alias for object. This makes it clear to the reader that password has no effect.

    @overload
    def export_to_pem(self, private_key: Literal[False] = False) -> bytes: ...
    @overload
    def export_to_pem(self, private_key: Literal[True], password: bytes | None) -> bytes: ...

This prevents errors by the user like export_to_pem(password=b"...") or export_to_pem(True, b"..."), but might be a bit more disruptive, especially when export_to_pem is wrapped by another function with a similar signature.

Please pick which of the three alternatives you think fits best.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Went with Unused, it feels the most sensible to me.

Copy link
Contributor

According to mypy_primer, this change has no effect on the checked open source code. 🤖🎉

@srittau srittau merged commit 68f4864 into python:main May 13, 2025
49 checks passed
mmingyu pushed a commit to mmingyu/typeshed that referenced this pull request May 16, 2025
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