conjugate icon indicating copy to clipboard operation
conjugate copied to clipboard

Improve NUMERIC protocol typing with proper variance and missing operators

Open Copilot opened this issue 1 month ago • 3 comments

Improve typing of the NUMERIC class

Analysis Complete: The NUMERIC Protocol class has several typing issues that can be improved.

Issues Identified:

  • [x] Import sorting issue (ruff I001)
  • [x] Parameters typed as NUMERIC instead of object (too restrictive, doesn't match Python's duck typing)
  • [x] Missing common numeric operators (__neg__, __pos__, __abs__, __pow__, __floordiv__, __mod__)
  • [x] Missing comparison operators (__lt__, __le__, __gt__, __ge__)
  • [x] Not marked as @runtime_checkable (best practice for protocols)
  • [x] Could use Self type for better type inference (requires typing_extensions for Python 3.10+)
  • [x] Pre-commit checks fixed (removed unused pytest import)

Changes Made:

1. Enhanced conjugate/_typing.py:

  • Fixed imports: Sorted imports properly and added runtime_checkable
  • Added Self type: Uses typing.Self (Python 3.11+) with fallback to typing_extensions.Self (Python 3.10)
  • Improved parameter types: Changed from NUMERIC to object for proper contravariance, matching Python's duck typing
  • Added missing operators:
    • Floor division: __floordiv__, __rfloordiv__
    • Modulo: __mod__, __rmod__
    • Power: __pow__, __rpow__
    • Unary: __neg__, __pos__, __abs__
    • Comparison: __lt__, __le__, __gt__, __ge__
  • Added documentation: Comprehensive docstring explaining the protocol's design and complex number exclusion
  • Made runtime checkable: Added @runtime_checkable decorator for isinstance() checks
  • Omitted __eq__, __ne__, __hash__: Intentionally excluded to support numpy arrays (which have __hash__ = None)
  • Clarified comments: Updated comment to accurately reflect that __eq__ and __ne__ are inherited from object

2. Added dependency in pyproject.toml:

  • Added typing-extensions>=4.0.0 to support Python 3.10

3. Created comprehensive tests in tests/test_typing.py:

  • Tests for protocol conformance (int, float, numpy arrays, etc.)
  • Tests for all arithmetic operations
  • Tests for reverse arithmetic operations
  • Tests for unary operations
  • Tests for comparison operations
  • Tests for mixed-type arithmetic
  • Tests for numpy broadcasting
  • Tests for type aliases
  • Documentation of complex number exclusion (they don't support // and %)

Design Decisions:

  • Complex numbers excluded: Complex numbers don't support floor division and modulo, so they don't conform to this protocol
  • __hash__ omitted: Allows numpy arrays (unhashable) to conform to the protocol
  • object for parameters: Enables duck typing (e.g., int + float works)

Verification:

  • [x] All 200 tests pass (including 17 new typing tests)
  • [x] Ruff linting passes with ALL rules enabled
  • [x] mypy strict mode passes
  • [x] pyright type checking passes
  • [x] Protocol works with int, float, numpy scalars, and numpy arrays
  • [x] Runtime isinstance() checks work correctly
  • [x] Code review feedback addressed
  • [x] Pre-commit checks pass
Original prompt

This section details on the original issue you should resolve

<issue_title>Improve typing of the NUMERIC class</issue_title> <issue_description>The NUMERIC class doesn't seems to do the job completely and has a lot of warnings and errors with the ruff linter. This can be improved</issue_description>

Comments on the Issue (you are @copilot in this section)

  • Fixes williambdean/conjugate#96

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot avatar Nov 02 '25 13:11 Copilot

Codecov Report

:white_check_mark: All modified and coverable lines are covered by tests. :white_check_mark: Project coverage is 95.03%. Comparing base (45a453a) to head (0d36a13). :warning: Report is 5 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #273      +/-   ##
==========================================
+ Coverage   95.00%   95.03%   +0.02%     
==========================================
  Files           9        9              
  Lines        1082     1087       +5     
==========================================
+ Hits         1028     1033       +5     
  Misses         54       54              

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

:rocket: New features to boost your workflow:
  • :snowflake: Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

codecov[bot] avatar Nov 02 '25 13:11 codecov[bot]

@copilot this is not passing pre-commit. Please run pre-commit run --all-files and fix any issues.

williambdean avatar Nov 20 '25 19:11 williambdean

@copilot this is not passing pre-commit. Please run pre-commit run --all-files and fix any issues.

Fixed in commit 013a55a. The pre-commit hook removed an unused pytest import from tests/test_typing.py. All pre-commit checks now pass.

Copilot avatar Nov 20 '25 19:11 Copilot