From 5d76c3e76d6e45a703f53ba24155b2e6efc664f1 Mon Sep 17 00:00:00 2001 From: Joey Marianer Date: Tue, 1 Jul 2025 16:43:21 -0700 Subject: [PATCH] Lupa stubs: Support get/set/del from Lua tables. Lua table values are all Any because we can't typecheck across language boundaries. Support unpack_returned_tuples in the LuaRuntime constructor. # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # Date: Tue Jul 1 16:43:21 2025 -0700 # # On branch main # Your branch is ahead of 'origin/main' by 1 commit. # (use "git push" to publish your local commits) # # Changes to be committed: # modified: lua51.pyi # modified: lua52.pyi # modified: lua53.pyi # modified: lua54.pyi # --- stubs/lupa/lupa/lua51.pyi | 33 ++++++++++++++++++++------------- stubs/lupa/lupa/lua52.pyi | 33 ++++++++++++++++++++------------- stubs/lupa/lupa/lua53.pyi | 33 ++++++++++++++++++++------------- stubs/lupa/lupa/lua54.pyi | 33 ++++++++++++++++++++------------- 4 files changed, 80 insertions(+), 52 deletions(-) diff --git a/stubs/lupa/lupa/lua51.pyi b/stubs/lupa/lupa/lua51.pyi index cdd4e4b096dd..1309241496b3 100644 --- a/stubs/lupa/lupa/lua51.pyi +++ b/stubs/lupa/lupa/lua51.pyi @@ -1,6 +1,7 @@ from _typeshed import MaybeNone -from collections.abc import Callable, Iterator +from collections.abc import Callable, Iterable from typing import Any, Final, Generic, TypeVar, type_check_only +from typing_extensions import TypeAlias __all__ = [ "LUA_VERSION", @@ -34,22 +35,29 @@ unpacks_lua_table_method: Callable[[Callable[..., Any]], Callable[..., Any]] # inner classes -@type_check_only -class _LuaIter: - def __iter__(self) -> Iterator[object]: ... - @type_check_only class _LuaTable: - def keys(self) -> _LuaIter: ... - def values(self) -> _LuaIter: ... - def items(self) -> _LuaIter: ... + def keys(self) -> Iterable[_LuaKey]: ... + def values(self) -> Iterable[_LuaObject]: ... + def items(self) -> Iterable[tuple[_LuaKey, _LuaObject]]: ... + def __getitem__(self, key: _LuaKey) -> _LuaObject: ... + def __setitem__(self, key: _LuaKey, value: _LuaObject) -> None: ... + def __delitem__(self, key: _LuaKey) -> None: ... + +# A Lua object can be a table or a primitive type. Because we have no way of +# knowing the actual type across languages, we simply use an Any for a Lua +# object. + +# A previous version of this code had +# _LuaObject: TypeAlias = _LuaTable | int | str | float | bool | None +# but that causes false type failures when running, e.g., `lua.globals()['foo']['bar']` +# (because `lua.globals()['foo']` is not known to be a nested table +_LuaKey: TypeAlias = str | int +_LuaObject: TypeAlias = Any @type_check_only class _LuaNoGC: ... -@type_check_only -class _LuaObject: ... - # classes _bint = TypeVar("_bint", bool, int) @@ -70,8 +78,7 @@ class LuaRuntime: lua_implementation: Final[str] lua_version: Final[tuple[int, int]] - # @classmethod - # def __cinit__(cls, unpack_return_tuples: bool) -> None: ... + def __init__(self, /, unpack_returned_tuples: bool) -> None: ... # def add_pending_unref(self, ref: int) -> None: ... # def clean_up_pending_unrefs(self) -> int: ... def get_max_memory(self, total: bool = False) -> int | MaybeNone: ... diff --git a/stubs/lupa/lupa/lua52.pyi b/stubs/lupa/lupa/lua52.pyi index cdd4e4b096dd..1309241496b3 100644 --- a/stubs/lupa/lupa/lua52.pyi +++ b/stubs/lupa/lupa/lua52.pyi @@ -1,6 +1,7 @@ from _typeshed import MaybeNone -from collections.abc import Callable, Iterator +from collections.abc import Callable, Iterable from typing import Any, Final, Generic, TypeVar, type_check_only +from typing_extensions import TypeAlias __all__ = [ "LUA_VERSION", @@ -34,22 +35,29 @@ unpacks_lua_table_method: Callable[[Callable[..., Any]], Callable[..., Any]] # inner classes -@type_check_only -class _LuaIter: - def __iter__(self) -> Iterator[object]: ... - @type_check_only class _LuaTable: - def keys(self) -> _LuaIter: ... - def values(self) -> _LuaIter: ... - def items(self) -> _LuaIter: ... + def keys(self) -> Iterable[_LuaKey]: ... + def values(self) -> Iterable[_LuaObject]: ... + def items(self) -> Iterable[tuple[_LuaKey, _LuaObject]]: ... + def __getitem__(self, key: _LuaKey) -> _LuaObject: ... + def __setitem__(self, key: _LuaKey, value: _LuaObject) -> None: ... + def __delitem__(self, key: _LuaKey) -> None: ... + +# A Lua object can be a table or a primitive type. Because we have no way of +# knowing the actual type across languages, we simply use an Any for a Lua +# object. + +# A previous version of this code had +# _LuaObject: TypeAlias = _LuaTable | int | str | float | bool | None +# but that causes false type failures when running, e.g., `lua.globals()['foo']['bar']` +# (because `lua.globals()['foo']` is not known to be a nested table +_LuaKey: TypeAlias = str | int +_LuaObject: TypeAlias = Any @type_check_only class _LuaNoGC: ... -@type_check_only -class _LuaObject: ... - # classes _bint = TypeVar("_bint", bool, int) @@ -70,8 +78,7 @@ class LuaRuntime: lua_implementation: Final[str] lua_version: Final[tuple[int, int]] - # @classmethod - # def __cinit__(cls, unpack_return_tuples: bool) -> None: ... + def __init__(self, /, unpack_returned_tuples: bool) -> None: ... # def add_pending_unref(self, ref: int) -> None: ... # def clean_up_pending_unrefs(self) -> int: ... def get_max_memory(self, total: bool = False) -> int | MaybeNone: ... diff --git a/stubs/lupa/lupa/lua53.pyi b/stubs/lupa/lupa/lua53.pyi index cdd4e4b096dd..1309241496b3 100644 --- a/stubs/lupa/lupa/lua53.pyi +++ b/stubs/lupa/lupa/lua53.pyi @@ -1,6 +1,7 @@ from _typeshed import MaybeNone -from collections.abc import Callable, Iterator +from collections.abc import Callable, Iterable from typing import Any, Final, Generic, TypeVar, type_check_only +from typing_extensions import TypeAlias __all__ = [ "LUA_VERSION", @@ -34,22 +35,29 @@ unpacks_lua_table_method: Callable[[Callable[..., Any]], Callable[..., Any]] # inner classes -@type_check_only -class _LuaIter: - def __iter__(self) -> Iterator[object]: ... - @type_check_only class _LuaTable: - def keys(self) -> _LuaIter: ... - def values(self) -> _LuaIter: ... - def items(self) -> _LuaIter: ... + def keys(self) -> Iterable[_LuaKey]: ... + def values(self) -> Iterable[_LuaObject]: ... + def items(self) -> Iterable[tuple[_LuaKey, _LuaObject]]: ... + def __getitem__(self, key: _LuaKey) -> _LuaObject: ... + def __setitem__(self, key: _LuaKey, value: _LuaObject) -> None: ... + def __delitem__(self, key: _LuaKey) -> None: ... + +# A Lua object can be a table or a primitive type. Because we have no way of +# knowing the actual type across languages, we simply use an Any for a Lua +# object. + +# A previous version of this code had +# _LuaObject: TypeAlias = _LuaTable | int | str | float | bool | None +# but that causes false type failures when running, e.g., `lua.globals()['foo']['bar']` +# (because `lua.globals()['foo']` is not known to be a nested table +_LuaKey: TypeAlias = str | int +_LuaObject: TypeAlias = Any @type_check_only class _LuaNoGC: ... -@type_check_only -class _LuaObject: ... - # classes _bint = TypeVar("_bint", bool, int) @@ -70,8 +78,7 @@ class LuaRuntime: lua_implementation: Final[str] lua_version: Final[tuple[int, int]] - # @classmethod - # def __cinit__(cls, unpack_return_tuples: bool) -> None: ... + def __init__(self, /, unpack_returned_tuples: bool) -> None: ... # def add_pending_unref(self, ref: int) -> None: ... # def clean_up_pending_unrefs(self) -> int: ... def get_max_memory(self, total: bool = False) -> int | MaybeNone: ... diff --git a/stubs/lupa/lupa/lua54.pyi b/stubs/lupa/lupa/lua54.pyi index cdd4e4b096dd..1309241496b3 100644 --- a/stubs/lupa/lupa/lua54.pyi +++ b/stubs/lupa/lupa/lua54.pyi @@ -1,6 +1,7 @@ from _typeshed import MaybeNone -from collections.abc import Callable, Iterator +from collections.abc import Callable, Iterable from typing import Any, Final, Generic, TypeVar, type_check_only +from typing_extensions import TypeAlias __all__ = [ "LUA_VERSION", @@ -34,22 +35,29 @@ unpacks_lua_table_method: Callable[[Callable[..., Any]], Callable[..., Any]] # inner classes -@type_check_only -class _LuaIter: - def __iter__(self) -> Iterator[object]: ... - @type_check_only class _LuaTable: - def keys(self) -> _LuaIter: ... - def values(self) -> _LuaIter: ... - def items(self) -> _LuaIter: ... + def keys(self) -> Iterable[_LuaKey]: ... + def values(self) -> Iterable[_LuaObject]: ... + def items(self) -> Iterable[tuple[_LuaKey, _LuaObject]]: ... + def __getitem__(self, key: _LuaKey) -> _LuaObject: ... + def __setitem__(self, key: _LuaKey, value: _LuaObject) -> None: ... + def __delitem__(self, key: _LuaKey) -> None: ... + +# A Lua object can be a table or a primitive type. Because we have no way of +# knowing the actual type across languages, we simply use an Any for a Lua +# object. + +# A previous version of this code had +# _LuaObject: TypeAlias = _LuaTable | int | str | float | bool | None +# but that causes false type failures when running, e.g., `lua.globals()['foo']['bar']` +# (because `lua.globals()['foo']` is not known to be a nested table +_LuaKey: TypeAlias = str | int +_LuaObject: TypeAlias = Any @type_check_only class _LuaNoGC: ... -@type_check_only -class _LuaObject: ... - # classes _bint = TypeVar("_bint", bool, int) @@ -70,8 +78,7 @@ class LuaRuntime: lua_implementation: Final[str] lua_version: Final[tuple[int, int]] - # @classmethod - # def __cinit__(cls, unpack_return_tuples: bool) -> None: ... + def __init__(self, /, unpack_returned_tuples: bool) -> None: ... # def add_pending_unref(self, ref: int) -> None: ... # def clean_up_pending_unrefs(self) -> int: ... def get_max_memory(self, total: bool = False) -> int | MaybeNone: ...