Skip to content

Conversation

termoshtt
Copy link
Member

@termoshtt termoshtt commented Aug 16, 2025

Summary

Fixes #233: Automatically generates Python stub methods for comparison operations (__eq__, __lt__, __le__, __gt__, __ge__) when PyO3 classes use the eq and ord attributes in their #[pyclass] decorator.

Problem

When using #[pyclass(eq, ord)] in PyO3, the Rust compiler automatically generates comparison methods for the class. However, pyo3-stub-gen was not generating corresponding Python stub methods, leading to missing type hints for these operations in IDEs and type checkers.

Solution

Implemented a three-phase solution that follows the existing architecture pattern:

1. Derive Phase (Metadata Collection)

  • Added Eq and Ord variants to the Attr enum in pyo3-stub-gen-derive/src/gen_stub/attr.rs
  • Enhanced attribute parsing to recognize eq and ord attributes in #[pyclass] decorators
  • Extended PyClassInfo to include has_eq and has_ord boolean flags

2. Runtime Phase (Type Information)

  • Updated runtime PyClassInfo in pyo3-stub-gen/src/type_info.rs with comparison flags
  • Fixed exception macro to include the new fields with default values

3. Generation Phase (Stub Creation)

  • Implemented comparison method generation in pyo3-stub-gen/src/generate/class.rs
  • Added add_eq_method() to generate __eq__(self, other: object) -> bool
  • Added add_ord_methods() to generate __lt__, __le__, __gt__, __ge__ methods
  • Integrated into ClassDef::from to automatically add methods when flags are set

Test Coverage

Added comprehensive test coverage in examples/pure/:

  • New test struct: ComparableStruct with #[pyclass(eq, ord)]
  • Python tests: Verify all comparison operations work correctly
  • Stub validation: Confirms proper type hints are generated

Generated Stubs

For a class like:

#[pyclass(eq, ord)]
struct ComparableStruct { ... }

The generator now produces:

class ComparableStruct:
    def __eq__(self, other: builtins.object) -> builtins.bool: ...
    def __lt__(self, other: builtins.object) -> builtins.bool: ...
    def __le__(self, other: builtins.object) -> builtins.bool: ...
    def __gt__(self, other: builtins.object) -> builtins.bool: ...
    def __ge__(self, other: builtins.object) -> builtins.bool: ...

Architecture

The implementation maintains proper separation of concerns:

  • Derive side: Only collects metadata about eq/ord presence
  • Generate side: Handles actual method creation and stub generation
  • No breaking changes: Existing functionality remains unchanged

This fixes issue #233 by automatically generating stub methods for
comparison operations (__eq__, __lt__, __le__, __gt__, __ge__) when
pyclass attributes eq and ord are used.

Changes:
- Add Eq and Ord variants to Attr enum
- Update attribute parsing to recognize eq/ord attributes
- Add comparison method generation in PyClassInfo
- Modify pyclass proc macro to submit PyMethodsInfo for comparison methods
- Make struct fields public to allow manual construction
- Add test case with ComparableStruct to verify functionality

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
@termoshtt termoshtt self-assigned this Aug 16, 2025
@termoshtt termoshtt changed the title Generate comparison method stubs for pyclass(eq, ord) Generate comparison method stubs for #[pyclass(eq, ord)] Aug 16, 2025
This redesigns the comparison method generation to follow proper
separation of concerns, fixing the architectural issues from the
previous implementation.

Changes:
- Revert pub fields in derive crate structs to maintain encapsulation
- Move comparison method generation from derive side to stub generation side
- Add has_eq/has_ord flags to PyClassInfo for metadata only
- Implement comparison method generation in ClassDef with proper architecture
- Update exception macro to include new PyClassInfo fields
- Maintain proper type information (object instead of typing.Any)

This ensures derive crate only handles metadata collection while
stub generation side handles actual method generation, creating
a cleaner and more maintainable architecture.

Fixes #233

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
@termoshtt termoshtt marked this pull request as ready for review August 16, 2025 15:21
@Copilot Copilot AI review requested due to automatic review settings August 16, 2025 15:21
Copy link
Contributor

@Copilot 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

This PR implements automatic generation of Python stub methods for comparison operations when PyO3 classes use the eq and ord attributes in their #[pyclass] decorator, addressing issue #233.

  • Adds support for detecting eq and ord attributes in #[pyclass] decorators
  • Automatically generates stub methods for __eq__, __lt__, __le__, __gt__, and __ge__ operations
  • Maintains architectural separation between derive-time metadata collection and generation-time stub creation

Reviewed Changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
pyo3-stub-gen/src/type_info.rs Adds has_eq and has_ord boolean fields to PyClassInfo struct
pyo3-stub-gen/src/lib.rs Updates documentation example to include new comparison fields
pyo3-stub-gen/src/generate/class.rs Implements comparison method generation logic with add_eq_method() and add_ord_methods()
pyo3-stub-gen/src/exception.rs Updates exception macro to include default values for new fields
pyo3-stub-gen-derive/src/gen_stub/pyclass.rs Adds parsing and processing for eq and ord attributes in derive phase
pyo3-stub-gen-derive/src/gen_stub/attr.rs Adds Eq and Ord variants to Attr enum and parsing logic
pyo3-stub-gen-derive/src/gen_stub.rs Updates documentation example with new fields
examples/pure/tests/test_python.py Adds comprehensive tests for comparison operations
examples/pure/src/lib.rs Adds ComparableStruct test class with #[pyclass(eq, ord)]
examples/pure/pure.pyi Shows generated stub output with comparison methods

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@termoshtt termoshtt merged commit c9c44ff into main Aug 16, 2025
26 checks passed
@termoshtt termoshtt deleted the pyclass-eq-ord branch August 16, 2025 15:23
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.

ord and eq not handled as modifyers to pyclass
1 participant