Skip to content

Fix saving __qualname__ of functions - #744

Open
dfremont wants to merge 3 commits into
uqfoundation:masterfrom
dfremont:fix_func_qualname
Open

Fix saving __qualname__ of functions#744
dfremont wants to merge 3 commits into
uqfoundation:masterfrom
dfremont:fix_func_qualname

Conversation

@dfremont

@dfremont dfremont commented Feb 6, 2026

Copy link
Copy Markdown

Summary

This PR fixes the saving of the __qualname__ attribute of functions when it is the same as __name__ but different from __code__.co_qualname (a situation that arises when using functools.wraps: see issue #602 for details).

Fixes #602. This changes existing behavior, so is technically not backwards-compatible, but I think the existing behavior was clearly wrong. (It was also inconsistent between module-level and local functions.)

Checklist

Documentation and Tests

  • Added relevant tests that run with python tests/__main__.py, and pass.

Release Management

  • Added "Fixes #NNN" in the PR body, referencing the issue (#NNN) it closes.
  • Added a comment to issue #NNN, linking back to this PR.
  • Added rationale for any breakage of backwards compatibility.
  • Requested a review.

@dfremont
dfremont marked this pull request as draft February 6, 2026 18:08
@dfremont
dfremont marked this pull request as ready for review February 6, 2026 18:16
@dfremont

dfremont commented Feb 6, 2026

Copy link
Copy Markdown
Author

Whoops, I forgot co_qualname doesn't exist in Python 3.10. Before it was introduced, types.FunctionType used co_name instead, so I've added code to fall back to that.

@mmckerns or @anivegesana (author of the specific line I modified) could you please review this when you have a moment?

@mmckerns

mmckerns commented Feb 7, 2026

Copy link
Copy Markdown
Member

The unfortunate thing about changing behavior is that we also have to make sure the changes to the code do not impact the ability to unpickle old pickles that were created before the change. I'll review your changes -- can you check your changes versus some old pickles? If it fails, we would need to add a shim to the code to handle old pickles.

@dfremont

dfremont commented Feb 8, 2026

Copy link
Copy Markdown
Author

Thanks, Mike. The 1-line change I made is in save_function, which is only invoked during pickling, not unpickling (if I understand correctly). So handling of existing pickles will not change.

@mmckerns

Copy link
Copy Markdown
Member

@dfremont: so save_function is decorated by register, so it's the function that is called when the unpickler encounters a FunctionType. So, it's definitely called on unpickling. The question is, by changing the behavior, are there now existing objects that cannot be unpickled because __name__ != co_qualname / co_name. I'd assume yes. Would adding an "or" to the condition solve it, so it's still backward compatible and catches the behavior that fixes #602?

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.

Metadata of wrapper functions not preserved

2 participants