Skip to content

Commit

Permalink
Added several more dunder protocols
Browse files Browse the repository at this point in the history
  • Loading branch information
jorenham committed Feb 23, 2024
1 parent bb5e20e commit 080f540
Show file tree
Hide file tree
Showing 2 changed files with 153 additions and 23 deletions.
26 changes: 26 additions & 0 deletions optype/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,30 @@
'CanAiter',
'CanAnd',
'CanAnext',
'CanAwait',
'CanBool',
'CanBuffer',
'CanBytes',
'CanCall',
'CanCeil',
'CanComplex',
'CanContains',
'CanDel',
'CanDelattr',
'CanDelete',
'CanDelitem',
'CanDir',
'CanDivmod',
'CanEnter',
'CanEq',
'CanExit',
'CanFloat',
'CanFloor',
'CanFloordiv',
'CanFormat',
'CanGe',
'CanGet',
'CanGetBound',
'CanGetattr',
'CanGetattribute',
'CanGetitem',
Expand All @@ -39,6 +47,7 @@
'CanITruediv',
'CanIXor',
'CanIndex',
'CanInitSubclass',
'CanInt',
'CanInvert',
'CanIter',
Expand Down Expand Up @@ -73,18 +82,22 @@
'CanRSub',
'CanRTruediv',
'CanRXor',
'CanReleaseBuffer',
'CanRepr',
'CanReversed',
'CanRound',
'CanRound1',
'CanRound2',
'CanRshift',
'CanSet',
'CanSetName',
'CanSetattr',
'CanSetitem',
'CanStr',
'CanSub',
'CanTruediv',
'CanTrunc',
'CanWith',
'CanXor',
'HasAnnotations',
'HasDict',
Expand All @@ -107,22 +120,30 @@
CanAiter,
CanAnd,
CanAnext,
CanAwait,
CanBool,
CanBuffer,
CanBytes,
CanCall,
CanCeil,
CanComplex,
CanContains,
CanDel,
CanDelattr,
CanDelete,
CanDelitem,
CanDir,
CanDivmod,
CanEnter,
CanEq,
CanExit,
CanFloat,
CanFloor,
CanFloordiv,
CanFormat,
CanGe,
CanGet,
CanGetBound,
CanGetattr,
CanGetattribute,
CanGetitem,
Expand All @@ -142,6 +163,7 @@
CanITruediv,
CanIXor,
CanIndex,
CanInitSubclass,
CanInt,
CanInvert,
CanIter,
Expand Down Expand Up @@ -176,18 +198,22 @@
CanRSub,
CanRTruediv,
CanRXor,
CanReleaseBuffer,
CanRepr,
CanReversed,
CanRound,
CanRound1,
CanRound2,
CanRshift,
CanSet,
CanSetName,
CanSetattr,
CanSetitem,
CanStr,
CanSub,
CanTruediv,
CanTrunc,
CanWith,
CanXor,
)
from ._has import (
Expand Down
150 changes: 127 additions & 23 deletions optype/_can.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# ruff: noqa: PYI034
from typing import Any, Protocol, overload, override, runtime_checkable
from collections.abc import Generator
from types import TracebackType
from typing import (
Any,
Protocol,
overload,
override,
runtime_checkable,
)


# Iterator types
Expand Down Expand Up @@ -41,32 +49,31 @@ def __bytes__(self) -> Y: ...

@runtime_checkable
class CanFormat[X: str, Y: str](Protocol):
# typeshed's object.__format__ stub is unnecessarily restrictive
def __format__(self, __x: X) -> Y: ... # type: ignore[override]

@runtime_checkable
class CanLt[X, Y](Protocol):
def __lt__(self, __x: X, /) -> Y: ...
def __lt__(self, __x: X) -> Y: ...

@runtime_checkable
class CanLe[X, Y](Protocol):
def __le__(self, __x: X, /) -> Y: ...
def __le__(self, __x: X) -> Y: ...

@runtime_checkable
class CanEq[X, Y](Protocol):
def __eq__(self, __x: X, /) -> Y: ... # type: ignore[override]
def __eq__(self, __x: X) -> Y: ... # type: ignore[override]

@runtime_checkable
class CanNe[X, Y](Protocol):
def __ne__(self, __x: X, /) -> Y: ... # type: ignore[override]
def __ne__(self, __x: X) -> Y: ... # type: ignore[override]

@runtime_checkable
class CanGt[X, Y](Protocol):
def __gt__(self, __x: X, /) -> Y: ...
def __gt__(self, __x: X) -> Y: ...

@runtime_checkable
class CanGe[X, Y](Protocol):
def __ge__(self, __x: X, /) -> Y: ...
def __ge__(self, __x: X) -> Y: ...

@runtime_checkable
class CanHash(Protocol):
Expand Down Expand Up @@ -111,9 +118,25 @@ def __dir__(self) -> Vs: ...
# 3.3.2.2. Implementing Descriptors
# https://docs.python.org/3/reference/datamodel.html#implementing-descriptors

# TODO: CanGet
# TODO: CanSet
# TODO: CanDelete
@runtime_checkable
class CanGetBound[T, V](Protocol):
def __get__(self, __obj: T, __cls: type[T] | None = ...) -> V: ...

@runtime_checkable
class CanGet[T, U, V](CanGetBound[T, V], Protocol):
@overload
def __get__(self, __obj: None, __cls: type[T]) -> U: ...
@overload
def __get__(self, __obj: T, __cls: type[T] | None = ...) -> V: ...

@runtime_checkable
class CanSet[T, V](Protocol):
def __set__(self, __obj: T, __v: V) -> Any: ...

@runtime_checkable
class CanDelete[T](Protocol):
def __delete__(self, __obj: T) -> Any: ...

# TODO: HasObjclass

# 3.3.2.4. `__slots__`
Expand All @@ -125,8 +148,21 @@ def __dir__(self) -> Vs: ...
# 3.3.3. Customizing class creation
# https://docs.python.org/3/reference/datamodel.html#customizing-class-creation

# TODO: CanInitSubclass
# TODO: CanSetName
@runtime_checkable
class CanInitSubclass[**Ps](Protocol):
# no positional-only are allowed
# cannot `Unpack` type args: https://github.com/python/typing/issues/1399
# workaround: use `**Ps` instead of `Ps: TypedDict`
def __init_subclass__(
cls,
*__dont_use_these_args: Ps.args,
**__kwargs: Ps.kwargs,
) -> Any: ...

@runtime_checkable
class CanSetName[T](Protocol):
def __set_name__(self, __cls: type[T], __name: str) -> Any: ...


# 3.3.3.2. Resolving MRO entries
# https://docs.python.org/3/reference/datamodel.html#resolving-mro-entries
Expand Down Expand Up @@ -160,7 +196,9 @@ def __dir__(self) -> Vs: ...
# 3.3.6. Emulating callable objects
# https://docs.python.org/3/reference/datamodel.html#emulating-callable-objects

# TODO: CanCall
@runtime_checkable
class CanCall[**Xs, Y](Protocol):
def __call__(self, *__xa: Xs.args, **__xk: Xs.kwargs) -> Y: ...


# 3.3.7. Emulating container types
Expand Down Expand Up @@ -446,9 +484,26 @@ def __ceil__(self) -> Y: ...
# 3.3.9. With Statement Context Managers
# https://docs.python.org/3/reference/datamodel.html#with-statement-context-managers

# TODO: CanEnter
# TODO: CanExit
# TODO: CanWith = CanEnter & CanExit
@runtime_checkable
class CanEnter[V](Protocol):
def __enter__(self) -> V: ...

@runtime_checkable
class CanExit(Protocol):
@overload
def __exit__(self, __tp: None, __ex: None, __tb: None) -> None: ...
@overload
def __exit__(
self,
__tp: type[BaseException],
__ex: BaseException,
__tb: TracebackType,
) -> None: ...

@runtime_checkable
class CanWith[V](CanEnter[V], CanExit, Protocol):
"""Intersection type of `CanEnter[V] & CanExit`, i.e. a contextmanager."""


# 3.3.10. Customizing positional arguments in class pattern matching
# https://docs.python.org/3/reference/datamodel.html#customizing-positional-arguments-in-class-pattern-matching
Expand All @@ -459,20 +514,39 @@ def __ceil__(self) -> Y: ...
# 3.3.11. Emulating buffer types
# https://docs.python.org/3/reference/datamodel.html#emulating-buffer-types

# TODO: CanBuffer
# TODO: CanReleaseBuffer

@runtime_checkable
class CanBuffer[B: int](Protocol):
def __buffer__(self, __b: B) -> memoryview: ...

@runtime_checkable
class CanReleaseBuffer(Protocol):
def __release_buffer__(self, __v: memoryview) -> None: ...


# 3.4.1. Awaitable Objects
# https://docs.python.org/3/reference/datamodel.html#awaitable-objects

# TODO: CanAwait

# This should be `None | asyncio.Future[Any]`. But that would make this
# incompatible with `collections.abc.Awaitable`, because it (annoyingly)
# uses `Any`...
type _MaybeFuture = Any

# 3.4.2. Coroutine Objects
# https://docs.python.org/3/reference/datamodel.html#coroutine-objects

# TODO: .send(_), .throw(_), .throw(_, _), .throw(_, _, _), .close() ???
@runtime_checkable
class CanAwait[V](Protocol):
# Technically speaking, this can return any
# `CanNext[None | asyncio.Future[Any]]`. But in theory, the return value
# of generators are currently impossible to type, because the return value
# of a `yield from _` is # piggybacked using a `raise StopIteration(value)`
# from `__next__`. So that also makes `__await__` theoretically
# impossible to type. In practice, typecheckers work around that, by
# accepting the lie called `collections.abc.Generator`...
@overload
def __await__(self: 'CanAwait[None]') -> CanNext[_MaybeFuture]: ...
@overload
def __await__(self: 'CanAwait[V]') -> Generator[_MaybeFuture, None, V]: ...


# 3.4.3. Asynchronous Iterators
Expand All @@ -493,3 +567,33 @@ def __aiter__(self) -> Y: ...
# TODO: CanAenter
# TODO: CanAexit
# TODO: CanAsyncWith = CanAenter & CanAexit


# Module `abc`
# https://docs.python.org/3/library/abc.html
# TODO: CanSubclasshook


# Module `copy`
# https://docs.python.org/3/library/copy.html

# TODO: CanCopy
# TODO: CanDeepCopy
# TODO: CanReplace (py313+)


# Module `pickle`
# https://docs.python.org/3/library/pickle.html#pickling-class-instances

# TODO: CanGetnewargsEx
# TODO: CanGetnewargs
# TODO: CanGetstate
# TODO: CanSetstate
# TODO: CanReduce
# TODO: CanReduceEx


# Module `sys`
# https://docs.python.org/3/library/sys.html

# TODO: CanSizeof

0 comments on commit 080f540

Please sign in to comment.