Skip to content

Conversation

@banteg
Copy link

@banteg banteg commented Feb 6, 2026

Summary

This PR aligns pyray type stubs with what the module actually exports at runtime.

Changes included:

  • generate module-level constants in create_stub_pyray.py from enum values + raylib.defines
  • model typedef-equivalent texture structs as aliases in stubs (Texture2D = Texture)
  • regenerate pyray/__init__.pyi with top-level names users access in practice (for example: BLEND_ALPHA, MOUSE_BUTTON_LEFT, RL_QUADS, RL_SRC_ALPHA, TEXTURE_FILTER_POINT)
  • add a stub parity test and a small typing smoke sample
  • run parity checks from tests/run_tests.sh and tests/run_tests_dynamic.sh
  • keep ty checks optional in runners (only executed when the ty CLI is available)
  • allow parity tests to target dynamic stubs via PYRAY_STUB_PATH

Motivation

Runtime exports and pyray/__init__.pyi had drifted, which produced false positives in type checkers for valid API usage.

In particular, this showed up in ty as unresolved module attributes and Texture/Texture2D assignability issues, despite runtime behavior being correct.

Validation

  • uv run --with pytest python -m pytest tests/test_pyray_stub_parity.py
  • uv run ty check tests/typing/pyray_stub_smoke.py
  • uv run --with mypy mypy tests/typing/pyray_stub_smoke.py
  • bash -n tests/run_tests.sh
  • bash -n tests/run_tests_dynamic.sh

@electronstudio
Copy link
Owner

Some (maybe all????) of the constants you have added were already present.

For example, you added ARROWS_SIZE but it's already there as GuiScrollBarProperty.ARROWS_SIZE.
You may be able to access it without using the full name for backwards compatibility but this is usage is deprecated, you should use the full GuiScrollBarProperty.ARROWS_SIZE, hence why there is deliberately no type hint for ARROWS_SIZE.

@banteg
Copy link
Author

banteg commented Feb 6, 2026

thanks, i'll narrow this pr to non-deprecated module-level constants and drop the blanket enum parity behavior, so deprecated shorthand names like ARROWS_SIZE won’t be newly typed. converting to draft for now.

@banteg banteg marked this pull request as draft February 6, 2026 18:33
@banteg
Copy link
Author

banteg commented Feb 6, 2026

thanks again for the quick feedback, and sorry for the initial overreach here.

i misunderstood the intended direction and typed far too many top-level names in my first pass. i've now narrowed this pr to match what I think is the existing policy:

  • removed blanket module-level typing for enum-member shorthand names (for example ARROWS_SIZE, BLEND_ALPHA, MOUSE_BUTTON_LEFT)
  • kept enum-class access as the typed path (for example GuiScrollBarProperty.ARROWS_SIZE, BlendMode.BLEND_ALPHA, MouseButton.MOUSE_BUTTON_LEFT)
  • kept module-level RL_* constants typed (excluding deprecated alias names like RL_SHADER_LOC_MAP_DIFFUSE / RL_SHADER_LOC_MAP_SPECULAR)
  • kept the Texture2D = Texture alias fix

if this still doesn’t match your intended API/stub direction, i can trim it further, including reducing RL_* to a smaller list or rework it however you prefer.

mostly coming here because i got hundreds of typecheck errors from ty for what i think is acceptable valid usage. some of them might be wrong deprecated usage, but im sure some are legitimately missing.

  25 error[unresolved-attribute]: Module `pyray` has no member `MOUSE_BUTTON_LEFT`
  24 error[unresolved-attribute]: Module `pyray` has no member `BLEND_ADDITIVE`
  19 error[unresolved-attribute]: Module `pyray` has no member `RL_FUNC_ADD`
  14 error[unresolved-attribute]: Module `pyray` has no member `RL_ZERO`
  10 error[unresolved-attribute]: Module `pyray` has no member `RL_ONE`
   9 error[unresolved-attribute]: Module `pyray` has no member `RL_ONE_MINUS_SRC_ALPHA`
   7 error[unresolved-attribute]: Module `pyray` has no member `TEXTURE_FILTER_BILINEAR`
   6 error[unresolved-attribute]: Module `pyray` has no member `BLEND_ALPHA`
   5 error[unresolved-attribute]: Module `pyray` has no member `RL_SRC_ALPHA`
   4 error[unresolved-attribute]: Module `pyray` has no member `TEXTURE_FILTER_POINT`
   4 error[unresolved-attribute]: Module `pyray` has no member `RL_QUADS`
   2 error[unresolved-attribute]: Module `pyray` has no member `SHADER_UNIFORM_VEC4`
   2 error[unresolved-attribute]: Module `pyray` has no member `MOUSE_BUTTON_RIGHT`
   2 error[unresolved-attribute]: Module `pyray` has no member `BLEND_CUSTOM_SEPARATE`
   1 error[unresolved-attribute]: Module `pyray` has no member `TEXTURE_WRAP_CLAMP`
   1 error[unresolved-attribute]: Module `pyray` has no member `SHADER_UNIFORM_VEC2`
   1 error[unresolved-attribute]: Module `pyray` has no member `SHADER_UNIFORM_INT`
   1 error[unresolved-attribute]: Module `pyray` has no member `SHADER_UNIFORM_FLOAT`
   1 error[unresolved-attribute]: Module `pyray` has no member `SHADER_LOC_VECTOR_VIEW`
   1 error[unresolved-attribute]: Module `pyray` has no member `SHADER_LOC_MATRIX_VIEW`
   1 error[unresolved-attribute]: Module `pyray` has no member `SHADER_LOC_MATRIX_PROJECTION`
   1 error[unresolved-attribute]: Module `pyray` has no member `SHADER_LOC_MATRIX_MVP`
   1 error[unresolved-attribute]: Module `pyray` has no member `SHADER_LOC_MATRIX_MODEL`
   1 error[unresolved-attribute]: Module `pyray` has no member `SHADER_LOC_MAP_NORMAL`
   1 error[unresolved-attribute]: Module `pyray` has no member `SHADER_LOC_MAP_DIFFUSE`
   1 error[unresolved-attribute]: Module `pyray` has no member `SHADER_LOC_COLOR_SPECULAR`
   1 error[unresolved-attribute]: Module `pyray` has no member `SHADER_LOC_COLOR_DIFFUSE`
   1 error[unresolved-attribute]: Module `pyray` has no member `SHADER_LOC_COLOR_AMBIENT`
   1 error[unresolved-attribute]: Module `pyray` has no member `MOUSE_BUTTON_MIDDLE`
   1 error[unresolved-attribute]: Module `pyray` has no member `BLEND_MULTIPLIED`
   1 error[unresolved-attribute]: Module `pyray` has no member `BLEND_CUSTOM`

@banteg banteg marked this pull request as ready for review February 6, 2026 18:54
@banteg
Copy link
Author

banteg commented Feb 6, 2026

i switched usages to enum-qualified forms (e.g. BlendMode.*, MouseButton.*, ShaderLocationIndex.*, etc.) instead of module-level shorthand in my project as it seems to be the intended path for typing.

after that cleanup, the only unresolved names left are these six rlgl constants:

  • RL_FUNC_ADD
  • RL_ZERO
  • RL_ONE
  • RL_ONE_MINUS_SRC_ALPHA
  • RL_SRC_ALPHA
  • RL_QUADS

so this no longer depends on typing broad top-level enum shorthand. it looks like a narrow missing-constants case for RL_* names only. there might be more omissions, it would appreciate some guidance here.

@electronstudio
Copy link
Owner

electronstudio commented Feb 7, 2026

Those are defined in raylib/defines.py (and imported by pyray). They aren't in pyray/__init__.pyi stub because the typehints for them are already in raylib/defines.py. I guess the type checker isn't finding them there. Needs investigation to confirm why and maybe copy them into pyray/__init__.pyi if necessary.

@electronstudio
Copy link
Owner

OK I'm pretty sure the way to fix this is as I suggested (but it would require me to do a little more processing to get the pyi format right from defines.py.)

However doing that means adding quite a few entries into the pyray toplevel namespace that pops up in Pycharm IDE autocomplete. That's not very nice, so I'm not sure if it's a good idea.

Another solution is just to import raylib.defines in your code and use them from there. That seems to pass type checking and keeps them all in the raylib.defines namespace. Maybe that should be the preferred way of using them and the top level way considered deprecated?

@banteg
Copy link
Author

banteg commented Feb 8, 2026

thanks, this is very helpful context.

i looked into this a bit more and i think the remaining RL_* errors are a checker/stub export clash rather than missing runtime symbols:

these constants are defined in raylib/defines.py and pyray imports them at runtime with a wildcard import, but type checkers like ty appear to treat pyray/__init__.pyi as authoritative and do not infer those runtime star-imported exports unless they’re represented in the stub.

that could explain why pyray.RL_FUNC_ADD/RL_ZERO/etc fail in type checking even though runtime works.

i think this leaves us with two options:

keep pyray stub tiny, and document recommended usage as raylib.defines.RL_* or add a very small set of RL_* exports to pyray/__init__.pyi (just the handful currently missing in practice) to preserve existing pyray.RL_* typed code without adding autocomplete noise at top level.

i don't have a strong preference here, i mainly want to align with your intended vision and direction for the api.

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.

2 participants