Skip to content

feat(functools): add Placeholder support and tests for functools.partial#276

Open
XuehaiPan wants to merge 1 commit intometaopt:mainfrom
XuehaiPan:functools
Open

feat(functools): add Placeholder support and tests for functools.partial#276
XuehaiPan wants to merge 1 commit intometaopt:mainfrom
XuehaiPan:functools

Conversation

@XuehaiPan
Copy link
Copy Markdown
Member

@XuehaiPan XuehaiPan commented Mar 31, 2026

Description

Add functools.Placeholder (Python 3.14+, PEP 309 extension) support for optree.functools.partial and re-export it from optree.functools for user convenience.

Since optree.functools.partial subclasses functools.partial, Placeholder already works out of the box — construction, calling, validation (trailing/keyword rejection), and repr are all handled by the stdlib's C implementation. This PR adds the re-export, documentation, and comprehensive test coverage.

Changes

optree/functools.py

  • Conditionally import and re-export functools.Placeholder on Python 3.14+
  • Extend __all__ to include 'Placeholder' on Python 3.14+
  • Add Placeholder usage example and leaf semantics note to partial docstring

tests/test_functools.py — 14 new test functions:

  • Roundtrip: basic, multiple placeholders, with keywords
  • Call semantics after roundtrip (fill slots, extra args, missing args error)
  • Leaf behavior: tree_leaves includes Placeholder, tree_map identity preserves it
  • Composition: Placeholder partial inside a larger tree
  • Shim path: wrapping functools.partial with Placeholder (with/without extra args)
  • Nested optree.functools.partial with Placeholder
  • Validation: trailing and keyword Placeholder rejection
  • Repr correctness
  • Re-export identity check

CHANGELOG.md — Added entry under [Unreleased] > Added

Design decisions

  • Placeholder is a leaf: Placeholder objects in partial.args are treated as leaves in the pytree, consistent with how any non-collection value in args is handled. This preserves correct accessor paths (GetAttrEntry('args') → SequenceEntry(i)).
  • No changes to __tree_flatten__/__tree_unflatten__: The existing implementation works correctly with Placeholder because it delegates construction to functools.partial.__new__().
  • No private details used: Tests use only public APIs (self.func, self.args, self.keywords, call behavior).

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds core functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation (update in the documentation)

Checklist

  • I have read the CONTRIBUTION guide. (required)
  • My change requires a change to the documentation.
  • I have updated the tests accordingly. (required for a bug fix or a new feature)
  • I have updated the documentation accordingly.
  • I have reformatted the code using make format. (required)
  • I have checked the code using make lint. (required)
  • I have ensured make test pass. (required)

@XuehaiPan XuehaiPan self-assigned this Mar 31, 2026
@XuehaiPan XuehaiPan added enhancement New feature or request python Something related to the Python source code labels Mar 31, 2026
@XuehaiPan XuehaiPan changed the title feat(functools): add Placeholder support and tests for partial feat(functools): add Placeholder support and tests for functools.partial Mar 31, 2026
@XuehaiPan XuehaiPan requested a review from Copilot March 31, 2026 15:01
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 31, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (bd32248) to head (472d0ea).

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #276   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           15        15           
  Lines         1561      1565    +4     
  Branches       207       207           
=========================================
+ Hits          1561      1565    +4     
Flag Coverage Δ
unittests 100.00% <100.00%> (ø)
unittests-cp310-Linux 100.00% <100.00%> (ø)
unittests-cp310-Windows 100.00% <100.00%> (ø)
unittests-cp310-macOS 100.00% <100.00%> (ø)
unittests-cp311-Linux 100.00% <100.00%> (ø)
unittests-cp311-Windows 100.00% <100.00%> (ø)
unittests-cp311-macOS 100.00% <100.00%> (ø)
unittests-cp312-Linux 100.00% <100.00%> (ø)
unittests-cp312-Windows 100.00% <100.00%> (ø)
unittests-cp312-macOS 100.00% <100.00%> (ø)
unittests-cp313-Linux 100.00% <100.00%> (ø)
unittests-cp313-Windows 100.00% <100.00%> (ø)
unittests-cp313-macOS 100.00% <100.00%> (ø)
unittests-cp313t-Linux 100.00% <100.00%> (ø)
unittests-cp313t-Windows 100.00% <100.00%> (ø)
unittests-cp313t-macOS 100.00% <100.00%> (ø)
unittests-cp314-Linux 100.00% <100.00%> (ø)
unittests-cp314-Windows 100.00% <100.00%> (ø)
unittests-cp314-macOS 100.00% <100.00%> (ø)
unittests-cp314t-Linux 100.00% <100.00%> (ø)
unittests-cp314t-Windows 100.00% <100.00%> (ø)
unittests-cp314t-macOS 100.00% <100.00%> (ø)
unittests-cp39-Linux 100.00% <100.00%> (ø)
unittests-cp39-Windows 100.00% <100.00%> (ø)
unittests-cp39-macOS 100.00% <100.00%> (ø)
unittests-pp311-Linux 100.00% <100.00%> (ø)
unittests-pp311-Windows 100.00% <100.00%> (ø)
unittests-pp311-macOS 100.00% <100.00%> (ø)
unittests-pydebug 100.00% <100.00%> (ø)
unittests-pydebug-cp310d-Linux 100.00% <100.00%> (ø)
unittests-pydebug-cp310d-Windows 100.00% <100.00%> (ø)
unittests-pydebug-cp310d-macOS 100.00% <100.00%> (ø)
unittests-pydebug-cp311d-Linux 100.00% <100.00%> (ø)
unittests-pydebug-cp311d-Windows 100.00% <100.00%> (ø)
unittests-pydebug-cp311d-macOS 100.00% <100.00%> (ø)
unittests-pydebug-cp312d-Linux 100.00% <100.00%> (ø)
unittests-pydebug-cp312d-Windows 100.00% <100.00%> (ø)
unittests-pydebug-cp312d-macOS 100.00% <100.00%> (ø)
unittests-pydebug-cp313d-Linux 100.00% <100.00%> (ø)
unittests-pydebug-cp313d-Windows 100.00% <100.00%> (ø)
unittests-pydebug-cp313d-macOS 100.00% <100.00%> (ø)
unittests-pydebug-cp313td-Linux 100.00% <100.00%> (ø)
unittests-pydebug-cp313td-Windows 100.00% <100.00%> (ø)
unittests-pydebug-cp313td-macOS 100.00% <100.00%> (ø)
unittests-pydebug-cp314d-Linux 100.00% <100.00%> (ø)
unittests-pydebug-cp314d-Windows 100.00% <100.00%> (ø)
unittests-pydebug-cp314d-macOS 100.00% <100.00%> (ø)
unittests-pydebug-cp314td-Linux 100.00% <100.00%> (ø)
unittests-pydebug-cp314td-Windows 100.00% <100.00%> (ø)
unittests-pydebug-cp314td-macOS 100.00% <100.00%> (ø)
unittests-pydebug-cp39d-Linux 100.00% <100.00%> (ø)
unittests-pydebug-cp39d-Windows 100.00% <100.00%> (ø)
unittests-pydebug-cp39d-macOS 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds Python 3.14+ functools.Placeholder convenience support to optree.functools by re-exporting the symbol, documenting usage with optree.functools.partial, and expanding the test suite to cover Placeholder roundtrips and call semantics in pytrees.

Changes:

  • Conditionally re-export functools.Placeholder from optree.functools and include it in __all__ on Python 3.14+.
  • Extend optree.functools.partial docstring with a Placeholder example and a note about leaf/identity semantics in pytrees.
  • Add comprehensive tests for Placeholder behavior across flatten/unflatten, tree_map, wrapping/nesting partials, validation errors, repr, and re-export identity.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
optree/functools.py Conditional import/re-export of Placeholder, __all__ update, and docstring updates for partial.
tests/test_functools.py Adds Placeholder-focused test coverage for roundtrips, calling behavior, tree interactions, and validation/repr.
CHANGELOG.md Records the new Placeholder support/re-export under [Unreleased] > Added.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@XuehaiPan XuehaiPan force-pushed the functools branch 2 times, most recently from c2a5336 to 3e538e8 Compare March 31, 2026 15:38
…artial`

Re-export `functools.Placeholder` (Python 3.14+) from `optree.functools`
and add comprehensive tests verifying that `optree.functools.partial`
works consistently with stdlib's `functools.partial` when Placeholders
are used in positional arguments.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request python Something related to the Python source code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants