-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
42a9818
commit 535c1f2
Showing
6 changed files
with
240 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
""" | ||
TODO: | ||
Create a descriptor and adorn the __get__ method with the @typing.overload decorator to ensure the functionality of the test case. | ||
NOTE: Craft at least two overload declarations: | ||
- one to handle the case when the instance is None (i.e., accessing TestClass.a), and another... | ||
- ...to cater to any instance of TestClass. | ||
NOTE: By explicitly binding the instance parameter to the TestClass class, the test cases can also be successfully passed. | ||
""" | ||
|
||
|
||
class Descriptor: | ||
def __get__(self, instance: ..., owner: ...): | ||
"""you don't need to implement this""" | ||
... | ||
|
||
|
||
## End of your code ## | ||
class TestClass: | ||
a = Descriptor() | ||
|
||
|
||
def descriptor_self(x: Descriptor) -> None: | ||
... | ||
|
||
|
||
def string_value(x: str) -> None: | ||
... | ||
|
||
|
||
descriptor_self(TestClass.a) | ||
string_value(TestClass().a) | ||
|
||
descriptor_self(TestClass().a) # expect-type-error | ||
string_value(TestClass.a) # expect-type-error |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
""" | ||
TODO: | ||
Define a descriptor, make test case works. | ||
""" | ||
|
||
from typing import overload, Self, Any | ||
|
||
|
||
class Descriptor: | ||
@overload | ||
def __get__(self, instance: None, owner: type) -> Self: | ||
... | ||
|
||
@overload | ||
def __get__(self, instance: Any, owner: type) -> str: | ||
... | ||
|
||
def __get__(self, instance: Any, owner: type) -> Self | str: | ||
if instance is None: | ||
return self | ||
|
||
return "" | ||
|
||
|
||
## End of your code ## | ||
class TestClass: | ||
a = Descriptor() | ||
|
||
|
||
def descriptor_self(x: Descriptor) -> None: | ||
... | ||
|
||
|
||
def string_value(x: str) -> None: | ||
... | ||
|
||
|
||
descriptor_self(TestClass.a) | ||
string_value(TestClass().a) | ||
|
||
descriptor_self(TestClass().a) # expect-type-error | ||
string_value(TestClass.a) # expect-type-error |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
""" | ||
TODO: | ||
a method-like descriptor, implements the `__get__` only. | ||
""" | ||
from typing import ParamSpec, TypeVar, Concatenate, Callable, Generic | ||
|
||
P = ParamSpec("P") | ||
T = TypeVar("T") | ||
R = TypeVar("R") | ||
|
||
|
||
class MyMethod(Generic[T, P, R]): | ||
def __init__(self, func: Callable[Concatenate[T, P], R]) -> None: | ||
self.func = func | ||
|
||
def __get__(self, instance, owner) -> None: | ||
return | ||
|
||
|
||
## End of your code ## | ||
class Foo: | ||
@MyMethod | ||
def do_something(self, value: int) -> None: | ||
... | ||
|
||
|
||
foo = Foo() | ||
|
||
Foo.do_something(foo, 1111) | ||
foo.do_something(1111) | ||
|
||
|
||
Foo.do_something(1111) # expect-type-error | ||
foo.do_something(11111, foo) # expect-type-error | ||
foo.do_something(foo, 11111) # expect-type-error |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
""" | ||
TODO: | ||
a method-like descriptor, implements the `__get__` only. | ||
""" | ||
from typing import Any, ParamSpec, TypeVar, Concatenate, Callable, Generic, overload | ||
|
||
P = ParamSpec("P") | ||
T = TypeVar("T") | ||
R = TypeVar("R") | ||
|
||
|
||
class MyMethod(Generic[T, P, R]): | ||
def __init__(self, func: Callable[Concatenate[T, P], R]) -> None: | ||
self.func = func | ||
|
||
@overload | ||
def __get__(self, instance: None, owner: type) -> Callable[Concatenate[T, P], R]: | ||
... | ||
|
||
@overload | ||
def __get__(self, instance: Any, owner: type) -> Callable[P, R]: | ||
... | ||
|
||
def __get__(self, instance: Any | None, owner: type): | ||
if instance is None: | ||
return self.func | ||
|
||
def wrapper(*args: P.args, **kwargs: P.kwargs) -> R: | ||
return self.func(instance, *args, **kwargs) | ||
|
||
return wrapper | ||
|
||
|
||
## End of your code ## | ||
class Foo: | ||
@MyMethod | ||
def do_something(self, value: int) -> None: | ||
... | ||
|
||
|
||
foo = Foo() | ||
|
||
Foo.do_something(foo, 1111) | ||
foo.do_something(1111) | ||
|
||
|
||
Foo.do_something(1111) # expect-type-error | ||
foo.do_something(11111, foo) # expect-type-error | ||
foo.do_something(foo, 11111) # expect-type-error |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
""" | ||
TODO: | ||
Enhance the Fn[VnCallable].into_callable method to return a Callable with an additional Any parameter at the beginning (using Concatenate). | ||
This should preserve the remaining parts of the function signature from VnCallable (i.e., parameters and their types, excluding the suffix), as well as the return type. | ||
""" | ||
|
||
from typing import Callable, TypeVar, Generic, Any, assert_type | ||
|
||
VnCallable = TypeVar("VnCallable", bound=Callable) | ||
|
||
|
||
class Fn(Generic[VnCallable]): | ||
# you MUST NOT modify the Generic defination. | ||
|
||
def __init__(self, f: VnCallable) -> None: | ||
self.f = f | ||
|
||
def into_callable(self): | ||
# TODO: annotate self parameter, not required to touch the function body. | ||
# NOTE: the test case requires a Any prefix param before VnCallable's parameters. | ||
# information is enough for type checker to infer these types. | ||
... | ||
|
||
|
||
## End of your code ## | ||
@Fn | ||
def example(a: int, b: str, c: float, *, d: bool = False) -> None: | ||
return | ||
|
||
|
||
assert_type(example.f(1, "1", 1.0, d=False), None) | ||
|
||
a: Any = 11111111 | ||
b = example.into_callable()(a, 1, "1", 1.0, d=False) | ||
assert_type(b, None) | ||
|
||
example.into_callable()(1, "1", 1.0, d=False) # expect-type-error |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
""" | ||
TODO: | ||
Enhance the Fn[VnCallable].into_callable method to return a Callable with an additional Any parameter at the beginning (using Concatenate). | ||
This should preserve the remaining parts of the function signature from VnCallable (i.e., parameters and their types, excluding the suffix), as well as the return type. | ||
""" | ||
|
||
from typing import Callable, Concatenate, ParamSpec, TypeVar, Generic, Any, assert_type | ||
|
||
P = ParamSpec("P") | ||
R = TypeVar("R", covariant=True) | ||
VnCallable = TypeVar("VnCallable", bound=Callable) | ||
|
||
|
||
class Fn(Generic[VnCallable]): | ||
def __init__(self, f: VnCallable) -> None: | ||
self.f = f | ||
|
||
def into_callable(self: "Fn[Callable[P, R]]") -> Callable[Concatenate[Any, P], R]: | ||
... | ||
|
||
|
||
## End of your code ## | ||
@Fn | ||
def example(a: int, b: str, c: float, *, d: bool = False) -> None: | ||
return | ||
|
||
|
||
assert_type(example.f(1, "1", 1.0, d=False), None) | ||
|
||
a: Any = 11111111 | ||
b = example.into_callable()(a, 1, "1", 1.0, d=False) | ||
assert_type(b, None) | ||
|
||
example.into_callable()(1, "1", 1.0, d=False) # expect-type-error |