Skip to content

ty: un-ignore invalid-type-arguments - #15392

Merged
cclauss merged 4 commits into
TheAlgorithms:masterfrom
Khushi-Tyagi9:ty-invalid-type-arguments-2
Sep 21, 2026
Merged

cclauss merged 4 commits into
TheAlgorithms:masterfrom
Khushi-Tyagi9:ty-invalid-type-arguments-2

Conversation

@Khushi-Tyagi9

Copy link
Copy Markdown
Contributor

Part of #15187.

Fixes the invalid-type-arguments diagnostics and drops the rule from the
ignore list in pyproject.toml.

  • k_nearest_neighbors.py: np.ndarray[float] isn't valid, because the first
    type parameter of ndarray is the shape. Changed to NDArray[np.float64]
    (and NDArray[np.int_] for the targets).
  • heap.py: Heap[int] was rejected because the Comparable protocol's
    methods accept keyword arguments, which int's don't. Made the other
    parameters positional-only, as ty suggested.

ty reports no invalid-type-arguments after this, and the doctests for both
files pass. Only annotations changed, nothing at runtime.

Describe your change

  • Add an algorithm?
  • Fix a bug or typo in an existing algorithm?
  • Add or change doctests? -- Note: Please avoid changing both code and tests in a single pull request.
  • Documentation change?

Checklist

  • I have read CONTRIBUTING.md.
  • This pull request is all my own work -- I have not plagiarized.
  • I know that pull requests will not be merged if they fail the automated tests.
  • This PR only changes one algorithm file. To ease review, please open separate PRs for separate algorithms.
  • All new Python files are placed inside an existing directory.
  • All filenames are in all lowercase characters with no spaces or dashes.
  • All functions and variable names follow Python naming conventions.
  • All function parameters and return values are annotated with Python type hints.
  • All functions have doctests that pass the automated testing.
  • All new algorithms include at least one URL that points to Wikipedia or another similar explanation.
  • If this pull request resolves one or more open issues, then the description above includes the issue number(s) with a closing keyword: "Fixes #ISSUE-NUMBER".

@algorithms-keeper algorithms-keeper Bot added awaiting reviews This PR is ready to be reviewed enhancement This PR modified some existing files labels Sep 21, 2026
@cclauss

cclauss commented Sep 21, 2026

Copy link
Copy Markdown
Member

@priya-sundaram-dev, please review. Are these the best solutions?

In data_structures/heap/heap.py do we need all three magic methods? __lt__, __gt__, and __eq__? Why does the slash placate ty?

In the move to use from numpy.typing import NDArray instead of np.ndarray seems like we are going backwards, but I know little about Numpy.

@priya-sundaram-dev

Copy link
Copy Markdown
Contributor

Reviewed — the changes are correct, and yes, these are the right solutions. Answers to your three questions:

Why does the / (positional-only) placate ty?
In typeshed, int/float/str declare their comparison dunders as positional-only, e.g. int.__lt__(self, value: int, /). Our Comparable protocol wrote def __lt__(self, other) without the slash, which advertises that other may be passed by keyword. Since int.__lt__ will not accept a keyword argument, int was not considered a structural match for Comparable, so Heap[int] failed invalid-type-arguments. Adding / makes the protocol's signature match the real dunder signatures, so int (and friends) now satisfy it. This is the standard way protocols for operators are written.

Do we need all three of __lt__, __gt__, __eq__?
Strictly, no — this heap is a max-heap and only ever calls > (in max_heapify: self.h[left_child] > self.h[violation]). So __gt__ alone is what the algorithm exercises. Keeping __lt__ too is a reasonable "this thing is orderable" convention and harmless. __eq__ is the odd one out: object already supplies __eq__ for every type, so declaring it in the protocol adds nothing for matching and (because it's abstract here) mostly just adds noise. I'd be comfortable dropping __eq__ and keeping __gt__ (+ optionally __lt__). Not a blocker either way.

Is NDArray a step backwards vs np.ndarray[float]?
It's actually the forward/correct direction. np.ndarray is generic over two parameters — np.ndarray[Shape, DType] — so np.ndarray[float] was never valid: it supplies only one parameter, and float is a Python type, not a np.dtype. numpy.typing.NDArray[np.float64] is numpy's own recommended alias and expands to np.ndarray[Any, np.dtype[np.float64]], which is what we actually mean ("an array of float64 of any shape"). So this fixes a latent type error rather than regressing.

One tiny nit: NDArray[np.int64] for the targets is fine; if you want to match platform-native ints you could use np.int_, but int64 is perfectly reasonable for label arrays. LGTM.

Removed unused __lt__ method from Comparable protocol and updated docstrings for clarity.
Removed unused import of total_ordering from functools.
@algorithms-keeper algorithms-keeper Bot added the tests are failing Do not merge until tests pass label Sep 21, 2026
@algorithms-keeper algorithms-keeper Bot removed the awaiting reviews This PR is ready to be reviewed label Sep 21, 2026
@cclauss
cclauss merged commit d9027b0 into TheAlgorithms:master Sep 21, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement This PR modified some existing files tests are failing Do not merge until tests pass

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants