Skip to content

cuda.core: accept dict for options in MemoryResource constructors - #2634

Open
juenglin wants to merge 2 commits into
NVIDIA:mainfrom
juenglin:mr-options-backward-compatibility
Open

cuda.core: accept dict for options in MemoryResource constructors#2634
juenglin wants to merge 2 commits into
NVIDIA:mainfrom
juenglin:mr-options-backward-compatibility

Conversation

@juenglin

@juenglin juenglin commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Restores undocumented dict acceptance for options in DeviceMemoryResource, ManagedMemoryResource, and PinnedMemoryResource constructors, which was inadvertently removed by #2619.

Background

#2619 removed | dict[str, object] from the Cython def __init__ annotations of all three memory-resource constructors. That change was correct in spirit—the documented public API should show only the typed Options dataclass—but it had an unintended runtime effect. Because all three options classes are @dataclass cdef class (Cython extension types), Cython enforces parameter type annotations at the call boundary of cdef class methods. Removing | dict[str, object] therefore made the constructors reject plain dicts with a TypeError before check_or_create_options was ever reached, silently breaking any code that relied on the dict shorthand.

What this PR does

The runtime annotations are restored to XxxOptions | dict[str, object] | None, preserving the backward-compatible dict path through check_or_create_options. At the same time the generated .pyi stubs are kept clean by a new # stub: directive mechanism in toolshed/run_stubgen_pyx.py.

Approaches considered

  1. Remove | dict and update all callers — correct policy, but a breaking change (PR docs(cuda.core): don't document APIs accept dict for options #2619).
  2. Untype the options parameter (options=None) — lets dict through but loses the type annotation in the generated stub entirely, giving users no type-checker guidance at all.
  3. Hard-code stub patches in run_stubgen_pyx.py — works but requires maintaining a list of constructor names in the hook, separate from the source.
  4. # stub: source directive (chosen) — the override lives next to the annotation it governs. Any .pyx parameter line of the form param: OrigType = default # stub: param: NewType causes the postprocessor to replace param: OrigType with param: NewType in the generated .pyi. Generic, grep-visible, and requires no new third-party dependency.

Changes

  • toolshed/run_stubgen_pyx.py: adds _collect_stub_overrides and _apply_stub_overrides; the main function now collects directives before invoking stubgen-pyx and applies them afterward.
  • Three _memory/*.pyx constructors: runtime annotations restored with | dict[str, object]; # stub: options: XxxOptions | None directive added.
  • Generated .pyi stubs updated accordingly (stubs are idempotent: re-running the pre-commit hook produces no further changes).
  • tests/memory/test_backward_compatibility.py: new tests asserting that each constructor accepts a plain dict for options.

closes #2248

@copy-pr-bot

copy-pr-bot Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@github-actions github-actions Bot added the cuda.core Everything related to the cuda.core module label Aug 14, 2026
@juenglin juenglin self-assigned this Aug 14, 2026
@juenglin juenglin added this to the cuda.core 1.2.0 milestone Aug 14, 2026
@juenglin

Copy link
Copy Markdown
Contributor Author

/ok to test 3c027ea

@github-actions

Copy link
Copy Markdown

@juenglin
juenglin requested review from leofang and mdboom and removed request for leofang August 14, 2026 20:25
@juenglin
juenglin marked this pull request as ready for review August 14, 2026 20:25
@juenglin juenglin added the documentation Improvements or additions to documentation label Aug 14, 2026
stub.write_bytes(first_line.replace(b"\\", b"/") + data[newline:])


def _collect_stub_overrides(root: pathlib.Path) -> dict[pathlib.Path, list[tuple[str, str]]]:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Significant changes or workarounds to stubgen-pyx should be submitted to that project upstream. (The existing workarounds in this script have already been submitted and merged, we are just waiting for a new release without regressions to update to, so the plan is always to live without this workaround script).

But the larger question is -- why do we need to have the annotation differ between the .pyx and the .pyi. I believe the annotation is ignored in the .pyx anyway. Unless in pure-Python mode, Cython only cares about the type before the argument name, not the type after the name and colon.

@mdboom mdboom left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think the stubgen-pyx workaround is ultimately unnecessary. Cython doesn't care about the annotation, so we can just set them directly to what we want them to be in the .pyi.

We can declare or not declare whether we accept a dict in the type annotation (that's sort of a larger question we are trying to answer offline -- whether we want to /commit/ to that).

But the tests on their own if useful if we decide we want to accept dicts going forward.

I should add Cython is a weird tool and Python type annotations being informational-only are pretty unique among languages. When you put them together (Cython pre-dates Python type annotations by at least a decade), it's a very confusing mishmash.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cuda.core Everything related to the cuda.core module documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[DOC]: cuda.core docs/type hints understate option params since dict is accepted at runtime but not documented

2 participants