Comments (6)
You were close. Python does allow overloading function definitions using the typing.overload decorator.
from typing import TypeVar, overload
C1 = TypeVar("C1")
C2 = TypeVar("C2")
C3 = TypeVar("C3")
@overload
def get_components(
self, ct1: type[C1], ct2: type[C2]
) -> list[tuple[int, tuple[C1, C2]]]:
pass
@overload
def get_components(
self, ct1: type[C1], ct2: type[C2], ct3: type[C3]
) -> list[tuple[int, tuple[C1, C2, C3]]]:
pass
...
def get_components(...):
... # Actual implementation.
Of course, this only handles typing for as many parameters as one is willing to make overloads for.
from esper.
Today I learned, thanks @HexDecimal. Big fan btw!
I quickly checked. Even though I get some warnings for the various get_coponents()
("Overloaded function incompatible", "Function dedeclared type of '' must return value.") the actual type inference works as shown here:
from typing import TypeVar, overload, List, Tuple
C1 = TypeVar("C1")
C2 = TypeVar("C2")
C3 = TypeVar("C3")
@overload
def get_components(ct1: type[C1], ct2: type[C2]) -> List[Tuple[int, Tuple[C1, C2]]]:
pass
@overload
def get_components(
ct1: type[C1], ct2: type[C2], ct3: type[C3]
) -> List[Tuple[int, Tuple[C1, C2, C3]]]:
pass
def get_components(*args):
for a in args:
print(a)
return [(1, [a for a in args])]
class A: pass
class B: pass
res = get_components(A, B)
id_ = res[0][0]
data = res[0][1]
from esper.
This would be my next iteration on the example. I've actually tested this one:
from typing import Any, List, Tuple, Type, TypeVar, overload
C1 = TypeVar("C1")
C2 = TypeVar("C2")
C3 = TypeVar("C3")
@overload
def get_components(__ct1: Type[C1], __ct2: Type[C2]) -> List[Tuple[int, Tuple[C1, C2]]]:
pass
@overload
def get_components(
__ct1: Type[C1], __ct2: Type[C2], __ct3: Type[C3]
) -> List[Tuple[int, Tuple[C1, C2, C3]]]:
pass
def get_components(*args: Type[object]) -> List[Tuple[int, Any]]:
for a in args:
print(a)
return [(1, tuple(a() for a in args))]
class A: pass
class B: pass
res = get_components(A, B)
id_ = res[0][0]
data = res[0][1]
assert isinstance(data, tuple)
assert isinstance(data[0], A)
The double underscore on parameters like __ct1
mark them as positional so that the main function doesn't need a **kwargs
parameter. The main function should be typed even though it isn't typed in most of the linked examples.
Be sure to test the types of the return values to make sure they match the expected type. Your example was returning a list of types instead of a tuple of instances. I've added asserts to check these.
I couldn't make a return type more specific than List[Tuple[int, Any]]
. The return type List[Tuple[int, Tuple[Any, ...]]]
seems to cause mismatches with the overloads for some reason I can't explain.
from esper.
Nice, you're getting there! :)
Same code as yours, with the following changes:
res = get_components(A, B)
id_ = res[0][0]
data = res[0][1]
reveal_type(data)
reveal_type(data[0])
reveal_type(data[1])
assert isinstance(data, tuple)
assert isinstance(data[0], A)
Different type checkers yield different results :)
❯ mypy type_overload2.py
type_overload2.py:34: note: Revealed type is "Tuple[type_overload2.A*, type_overload2.B*]"
type_overload2.py:35: note: Revealed type is "type_overload2.A*"
type_overload2.py:36: note: Revealed type is "type_overload2.B*"
❯ pyright type_overload2.py
No configuration file found.
No pyproject.toml file found.
stubPath /home/stefan/tmp/type_overload/typings is not a valid directory.
Assuming Python platform Linux
Searching for source files
Found 1 source file
/home/stefan/tmp/type_overload/type_overload2.py
/home/stefan/tmp/type_overload/type_overload2.py:10:57 - error: Function with declared type of "List[Tuple[int, Tuple[C1@get_components, C2@get_components]]]" must return value
Type "None" cannot be assigned to type "List[Tuple[int, Tuple[C1@get_components, C2@get_components]]]" (reportGeneralTypeIssues)
/home/stefan/tmp/type_overload/type_overload2.py:17:6 - error: Function with declared type of "List[Tuple[int, Tuple[C1@get_components, C2@get_components, C3@get_components]]]" must return value
Type "None" cannot be assigned to type "List[Tuple[int, Tuple[C1@get_components, C2@get_components, C3@get_components]]]" (reportGeneralTypeIssues)
/home/stefan/tmp/type_overload/type_overload2.py:34:13 - info: Type of "data" is "Tuple[A, B]"
/home/stefan/tmp/type_overload/type_overload2.py:35:13 - info: Type of "data[0]" is "A"
/home/stefan/tmp/type_overload/type_overload2.py:36:13 - info: Type of "data[1]" is "B"
/home/stefan/tmp/type_overload/type_overload2.py:21:5 - error: Overloaded function implementation is not consistent with signature of overload 1
Type "(*args: Type[object]) -> List[Tuple[int, Any]]" cannot be assigned to type "(__ct1: Type[C1@get_components], __ct2: Type[C2@get_components]) -> List[Tuple[int, Tuple[C1@get_components, C2@get_components]]]"
Parameter 1: type "Type[C1@get_components]" cannot be assigned to type "Type[object]"
Type "Type[C1@get_components]" cannot be assigned to type "Type[object]"
Parameter 2: type "Type[C2@get_components]" cannot be assigned to type "Type[object]"
Type "Type[C2@get_components]" cannot be assigned to type "Type[object]" (reportGeneralTypeIssues)
/home/stefan/tmp/type_overload/type_overload2.py:21:5 - error: Overloaded function implementation is not consistent with signature of overload 2
Type "(*args: Type[object]) -> List[Tuple[int, Any]]" cannot be assigned to type "(__ct1: Type[C1@get_components], __ct2: Type[C2@get_components], __ct3: Type[C3@get_components]) -> List[Tuple[int, Tuple[C1@get_components, C2@get_components, C3@get_components]]]"
Parameter 1: type "Type[C1@get_components]" cannot be assigned to type "Type[object]"
Type "Type[C1@get_components]" cannot be assigned to type "Type[object]"
Parameter 2: type "Type[C2@get_components]" cannot be assigned to type "Type[object]"
Type "Type[C2@get_components]" cannot be assigned to type "Type[object]"
Parameter 3: type "Type[C3@get_components]" cannot be assigned to type "Type[object]"
Type "Type[C3@get_components]" cannot be assigned to type "Type[object]" (reportGeneralTypeIssues)
4 errors, 0 warnings, 3 infos
Completed in 0.702sec
from esper.
I checked with Pyright.
Replace pass
with ...
in the overload functions to fix the must return value
errors.
I couldn't fix the type, but I could suppress the remaining errors by replacing Type[object]
with Type[Any]
.
The return type List[Tuple[int, Tuple[Any, ...]]]
works with Pyright but not with MyPy.
Careful with reveal_type
, this just tells you want the type checker thinks the type is, which may not be the names real type. Verify types with isinstance
in tests.
from esper.
The solution above works fine. I will write a pull request.
Maybe there will be a more elegant solution in the future using TypeVarTuple
but it is not yet implemented by mypy and the documentation says nothing that I read of about type[TypeVarTuple]
.
Components = TypeVarTuple("Components")
def get_components(
self, *component_types: Unpack[type[Components]]
) -> Iterator[tuple[EntityID, Components]]:
# implementation here
from esper.
Related Issues (20)
- esper.current_world not usable as a module-level property HOT 2
- Initializing the world is not working HOT 1
- Avoid unnecessary multiple dict lookup inside `has_components` function
- Create an entity with a specific id HOT 4
- Try another ECS implementation - ecs_pattern library HOT 2
- Typing of world under the processor class HOT 3
- Testing esper HOT 4
- mypy `get_components` gives "object" type HOT 1
- Relationships HOT 8
- `World().create_entity()` does not create entity if no components are given HOT 1
- `remove_component()` method removes entity if no more components left HOT 3
- Add mypy to unit tests HOT 2
- Querying entities with denylist of components HOT 5
- API Design : Why so much OOP ? HOT 20
- "Quick start" in README is targeting old version HOT 3
- Seeking Guidance on Persisting and Loading Esper from a Database HOT 2
- Is esper Thread-Safe for Multi-threaded Environments? HOT 5
- Why roll up world into esper module? HOT 4
- Event handlers set within a function don't remain once the block scope exits. Why use weak references here? HOT 4
- Event System does not preserve event handlers upon switching context HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from esper.