Skip to content

Commit

Permalink
TYPING Remove uses of abc.register
Browse files Browse the repository at this point in the history
Mypy doesn't understand `@abc.register`:
python/mypy#2922
so we should subclass the abc directly instead. This requires using a
custom metaclass which is simultaneously a subclass of JsProxy and ABCMeta.
  • Loading branch information
hoodmane committed Dec 4, 2023
1 parent 2cdca2e commit 568d294
Showing 1 changed file with 40 additions and 10 deletions.
50 changes: 40 additions & 10 deletions src/py/_pyodide/_core_docs.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
import sys
from abc import ABCMeta
from collections.abc import (
AsyncIterator,
Awaitable,
Expand All @@ -10,12 +11,13 @@
KeysView,
Mapping,
MutableMapping,
MutableSequence,
Sequence,
ValuesView,
)
from functools import reduce
from types import TracebackType
from typing import IO, Any, Generic, TypeVar, overload
from typing import IO, Any, Generic, Protocol, TypeVar, overload

from .docs_argspec import docs_argspec

Expand Down Expand Up @@ -87,6 +89,10 @@ def __subclasscheck__(cls, subclass):
return any(cls_flag & subclass_flags == cls_flag for cls_flag in cls_flags)


class _ABCMeta(_JsProxyMetaClass, ABCMeta):
pass


# We want to raise an error if someone tries to instantiate JsProxy directly
# since it doesn't mean anything. But we have a few reasons to do so internally.
# So we raise an error unless this private token is passed as an argument.
Expand Down Expand Up @@ -790,15 +796,31 @@ def __call__(self):
pass


class JsArray(JsIterable[T], Generic[T]):
class JsArray(JsIterable[T], Generic[T], MutableSequence[T], metaclass=_ABCMeta):
"""A JsProxy of an :js:class:`Array`, :js:class:`NodeList`, or :js:class:`TypedArray`"""

_js_type_flags = ["IS_ARRAY", "IS_NODE_LIST", "IS_TYPEDARRAY"]

def __getitem__(self, idx: int | slice) -> T:
@overload
def __getitem__(self, idx: int) -> T:
...

@overload
def __getitem__(self, idx: slice) -> "JsArray[T]":
...

def __getitem__(self, idx):
raise NotImplementedError

def __setitem__(self, idx: int | slice, value: T) -> None:
@overload
def __setitem__(self, idx: int, value: T) -> None:
...

@overload
def __setitem__(self, idx: slice, value: Iterable[T]) -> None:
...

def __setitem__(self, idx, value):
pass

def __delitem__(self, idx: int | slice) -> None:
Expand Down Expand Up @@ -872,8 +894,7 @@ def subarray(
buffer: JsBuffer


@Mapping.register
class JsMap(JsIterable[KT], Generic[KT, VTco]):
class JsMap(JsIterable[KT], Generic[KT, VTco], Mapping[KT, VTco], metaclass=_ABCMeta):
"""A JavaScript Map
To be considered a map, a JavaScript object must have a ``get`` method, it
Expand All @@ -889,7 +910,7 @@ def __getitem__(self, idx: KT) -> VTco:
def __len__(self) -> int:
return 0

def __contains__(self, idx: KT) -> bool:
def __contains__(self, idx: object) -> bool:
raise NotImplementedError

def keys(self) -> KeysView[KT]:
Expand Down Expand Up @@ -918,8 +939,17 @@ def get(self, key: KT, default: Any = None, /) -> VTco:
raise NotImplementedError


@MutableMapping.register
class JsMutableMap(JsMap[KT, VT], Generic[KT, VT]):
class _SupportsKeysAndGetItem(Protocol[KT, VTco]):
def keys(self) -> Iterable[KT]:
...

def __getitem__(self, __key: KT) -> VTco:
...


class JsMutableMap(
JsMap[KT, VT], Generic[KT, VT], MutableMapping[KT, VT], metaclass=_ABCMeta
):
"""A JavaScript mutable map
To be considered a mutable map, a JavaScript object must have a ``get``
Expand Down Expand Up @@ -964,7 +994,7 @@ def clear(self) -> None:
"""Empty out the map entirely."""

@overload
def update(self, __m: Mapping[KT, VT], **kwargs: VT) -> None:
def update(self, __m: _SupportsKeysAndGetItem[KT, VT], **kwargs: VT) -> None:
...

@overload
Expand Down

0 comments on commit 568d294

Please sign in to comment.