Skip to content

Commit

Permalink
implement advanced overwrites.
Browse files Browse the repository at this point in the history
this is also needed for #45
  • Loading branch information
CodeSteak committed Dec 5, 2021
1 parent a45ec8c commit 24fc50a
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 123 deletions.
122 changes: 2 additions & 120 deletions python/deps/untypy/untypy/impl/interface.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
from collections.abc import Iterator, Iterable
from typing import TypeVar, Optional, Any, Generic, Dict, List, Set, Tuple, Protocol, Union
from typing import TypeVar, Optional, Any, Generic, Dict, List, Set, Tuple, Protocol

from untypy.error import UntypyAttributeError, UntypyTypeError, Location, Frame, NO_GIVEN
from untypy.impl.interfaces.wlist import WList
from untypy.impl.protocol import ProtocolChecker
from untypy.impl.wrappedclass import WrappedType
from untypy.interfaces import TypeCheckerFactory, TypeChecker, CreationContext, ExecutionContext
from untypy.util import ReplaceTypeExecutionContext


def overwrite(fn):
setattr(fn, '__overwrite', True)
return fn


A = TypeVar("A")
B = TypeVar("B")

Expand Down Expand Up @@ -100,119 +95,6 @@ def __setitem__(self, key: K, value: V) -> None:
pass


I = TypeVar("I")


def cast_wlist(lst) -> list:
if hasattr(lst, '_WrappedClassFunction__inner'):
return lst._WrappedClassFunction__inner
else:
return lst

class WList(Generic[I], list):
# doc @ https://docs.python.org/3/tutorial/datastructures.html
# and https://docs.python.org/3/library/stdtypes.html#common-sequence-operations
# Exact signatures are undocumented :/
# HINT: Argument names must match.

def append(self, object: I) -> None:
pass

def extend(self, iterable: Iterable[I]) -> None:
pass

def insert(self, i: int, x: I) -> None:
pass

def remove(self, x: I) -> None:
pass

def pop(self, i: int = -1) -> Optional[I]:
pass

def clear(self) -> None:
pass

def index(self, x: I, start: Optional[int] = None, end: Optional[int] = None) -> int:
# get index of list
pass

def count(self, x: I) -> int:
pass

def sort(self, *, key: Any = None, reverse: bool = False) -> None:
# inner list will check type of key.
pass

def __contains__(self, item: I) -> bool:
pass

def __delitem__(self, i: Union[int, slice]):
pass

def __getitem__(self, item: Union[int, slice]) -> Any: # cannot be expressed in type system
pass

def __iadd__(self, other: Iterable[I]) -> Any: # returns self
pass

def __imul__(self, n: int) -> Any: # returns self
pass

def __iter__(self) -> Iterator[I]:
pass

def __setitem__(self, key: Union[int, slice], value: Any) -> None:
pass

@overwrite
def __radd__(self, other):
return cast_wlist(other) + cast_wlist(self)

@overwrite
def __lt__(self, other):
return cast_wlist(self).__lt__(cast_wlist(other))

@overwrite
def __le__(self, other):
return cast_wlist(self).__le__(cast_wlist(other))

@overwrite
def __eq__(self, other):
return cast_wlist(self).__eq__(cast_wlist(other))

@overwrite
def __ne__(self, other):
return cast_wlist(self).__ne__(cast_wlist(other))

@overwrite
def __gt__(self, other):
return cast_wlist(self).__gt__(cast_wlist(other))

@overwrite
def __ge__(self, other):
return cast_wlist(self).__ge__(cast_wlist(other))

# lower type on
# __add__
# __mul__
# copy

# Type fixed by std impl
# __repr__
# __reversed__
# __len__
# reverse

# type would be any
# __eq__
# __ge__
# __gt__
# __le__
# __lt__
# __ne__
#


I = TypeVar("I")

Expand Down
Empty file.
6 changes: 6 additions & 0 deletions python/deps/untypy/untypy/impl/interfaces/util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
def overwrite(typ):
def inner(fn):
setattr(fn, '__overwrite', typ)
return fn

return inner
142 changes: 142 additions & 0 deletions python/deps/untypy/untypy/impl/interfaces/wlist.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
from typing import TypeVar, Generic, Iterable, Optional, Union, Any, Iterator

from untypy.impl.interfaces.util import overwrite
from untypy.interfaces import CreationContext
from untypy.util import ReturnExecutionContext

I = TypeVar("I")


def sig_getitem():
def __getitem__(self, item: Union[int, slice]) -> Union[I, list[I]]:
pass

return __getitem__


def cast_wlist(lst) -> list:
if hasattr(lst, '_WrappedClassFunction__inner'):
return lst._WrappedClassFunction__inner
else:
return lst


class WList(Generic[I], list):
# doc @ https://docs.python.org/3/tutorial/datastructures.html
# and https://docs.python.org/3/library/stdtypes.html#common-sequence-operations
# Exact signatures are undocumented :/
# HINT: Argument names must match.

def append(self, object: I) -> None:
pass

def extend(self, iterable: Iterable[I]) -> None:
pass

def insert(self, i: int, x: I) -> None:
pass

def remove(self, x: I) -> None:
pass

def pop(self, i: int = -1) -> Optional[I]:
pass

def clear(self) -> None:
pass

def index(self, x: I, start: Optional[int] = None, end: Optional[int] = None) -> int:
# get index of list
pass

def count(self, x: I) -> int:
pass

def sort(self, *, key: Any = None, reverse: bool = False) -> None:
# inner list will check type of key.
pass

def __contains__(self, item: I) -> bool:
pass

def __delitem__(self, i: Union[int, slice]):
pass

@overwrite("advanced")
def __getitem__(self, ctx: CreationContext):
# self is WrappedClassFunction

u_checker = ctx.find_checker(Union[int, slice])
inner_checker = ctx.find_checker(I)

# TODO: implement some kind caching maybe.
me_checker = lambda: ctx.find_checker(list[I])

def inner(me, item):
ret_ctx = me._WrappedClassFunction__return_ctx
if ret_ctx is None:
ret_ctx = ReturnExecutionContext(self)

if isinstance(item, int):
item = me._WrappedClassFunction__inner[item]
return inner_checker.check_and_wrap(item, ret_ctx)
elif isinstance(item, slice):
item = me._WrappedClassFunction__inner[item]
return me_checker().check_and_wrap(item, ret_ctx)
else:
# TODO:
raise NotImplementedError()

setattr(self, '__original', sig_getitem())
return inner

def __iadd__(self, other: Iterable[I]) -> Any: # returns self
pass

def __imul__(self, n: int) -> Any: # returns self
pass

def __iter__(self) -> Iterator[I]:
pass

def __setitem__(self, key: Union[int, slice], value: Any) -> None:
pass

@overwrite("simple")
def __radd__(self, other):
return cast_wlist(other) + cast_wlist(self)

@overwrite("simple")
def __lt__(self, other):
return cast_wlist(self).__lt__(cast_wlist(other))

@overwrite("simple")
def __le__(self, other):
return cast_wlist(self).__le__(cast_wlist(other))

@overwrite("simple")
def __eq__(self, other):
return cast_wlist(self).__eq__(cast_wlist(other))

@overwrite("simple")
def __ne__(self, other):
return cast_wlist(self).__ne__(cast_wlist(other))

@overwrite("simple")
def __gt__(self, other):
return cast_wlist(self).__gt__(cast_wlist(other))

@overwrite("simple")
def __ge__(self, other):
return cast_wlist(self).__ge__(cast_wlist(other))

# lower type on
# __add__
# __mul__
# copy

# Type fixed by std impl
# __repr__
# __reversed__
# __len__
# reverse
25 changes: 22 additions & 3 deletions python/deps/untypy/untypy/impl/wrappedclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def raise_err():

if overwrites is not None and hasattr(overwrites, attr):
a = getattr(overwrites, attr)
if hasattr(a, '__overwrite'):
if hasattr(a, '__overwrite') and getattr(a, '__overwrite') == 'simple':
list_of_attr[attr] = getattr(overwrites, attr)
continue

Expand All @@ -99,8 +99,16 @@ def raise_err():
(signature, checker) = find_signature(original, ctx)
implementation_fn = getattr(implementation_template, attr)
if implementation_fn is not None:
list_of_attr[attr] = WrappedClassFunction(implementation_fn, signature, checker,
create_fn=create_fn, declared=declared).build()
if overwrites is not None and hasattr(overwrites, attr) and hasattr(getattr(overwrites, attr),
'__overwrite') and getattr(
getattr(overwrites, attr), '__overwrite') == 'advanced':
list_of_attr[attr] = WrappedClassFunction(implementation_fn, signature, checker,
create_fn=create_fn,
declared=declared).build_overwrite(
getattr(overwrites, attr), ctx)
else:
list_of_attr[attr] = WrappedClassFunction(implementation_fn, signature, checker,
create_fn=create_fn, declared=declared).build()
except ValueError as e:
# this fails sometimes on built-ins.
# "ValueError: no signature found for builtin"
Expand Down Expand Up @@ -132,6 +140,17 @@ def __init__(self,
if hasattr(self.inner, "__fc"):
self.fc = getattr(self.inner, "__fc")

def build_overwrite(self, f, ctx: CreationContext):
fn = self.inner

w = f(self, ctx)

setattr(w, '__wrapped__', fn)
setattr(w, '__name__', fn.__name__)
setattr(w, '__signature__', self.signature)
setattr(w, '__wf', self)
return w

def build(self):
fn = self.inner
name = fn.__name__
Expand Down

0 comments on commit 24fc50a

Please sign in to comment.