[lupa] Improve Lua table annotations (#14359)

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.
This commit is contained in:
Joey Marianer
2025-08-20 03:03:02 -07:00
committed by GitHub
parent 673cecca79
commit 706320ca03
4 changed files with 80 additions and 52 deletions
+20 -13
View File
@@ -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: ...
+20 -13
View File
@@ -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: ...
+20 -13
View File
@@ -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: ...
+20 -13
View File
@@ -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: ...