Skip to content

Add TypeForm support #40

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ dependencies = [
"attrs >=23.1.0",
"cattrs >=23.1.2",
"sentinel-value >=1.0.0",
"typing-extensions >=4.9.0",
"typing-extensions >=4.13.1",
]

[tool.setuptools_scm]
Expand Down
18 changes: 8 additions & 10 deletions tcod/ecs/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
MutableMapping,
MutableSet,
Tuple,
Type,
TypeVar,
Union,
overload,
Expand All @@ -22,7 +21,7 @@

import attrs
from sentinel_value import sentinel
from typing_extensions import Self, deprecated
from typing_extensions import Self, TypeForm, deprecated

Check failure on line 24 in tcod/ecs/entity.py

View workflow job for this annotation

GitHub Actions / mypy (3.12)

Module "typing_extensions" has no attribute "TypeForm"

Check failure on line 24 in tcod/ecs/entity.py

View workflow job for this annotation

GitHub Actions / mypy (3.12)

Module "typing_extensions" has no attribute "TypeForm"

import tcod.ecs.callbacks
import tcod.ecs.query
Expand Down Expand Up @@ -389,7 +388,7 @@


@attrs.define(eq=False, frozen=True, weakref_slot=False)
class EntityComponents(MutableMapping[Union[Type[Any], Tuple[object, Type[Any]]], object]):
class EntityComponents(MutableMapping[Union[TypeForm[Any], Tuple[object, TypeForm[Any]]], Any]):
"""A proxy attribute to access an entities components like a dictionary.

See :any:`Entity.components`.
Expand Down Expand Up @@ -474,7 +473,7 @@
*(_components_by_entity.get(entity, ()) for entity in _traverse_entities(self.entity, self.traverse))
)

def __contains__(self, key: ComponentKey[object]) -> bool: # type: ignore[override]
def __contains__(self, key: ComponentKey[object]) -> bool:
"""Return True if this entity has the provided component."""
_components_by_entity = self.entity.registry._components_by_entity
return any(
Expand All @@ -500,21 +499,20 @@
self.set(value)

@deprecated("This method has been deprecated. Iterate over items instead.", category=FutureWarning)
def by_name_type(self, name_type: type[_T1], component_type: type[_T2]) -> Iterator[tuple[_T1, type[_T2]]]:
def by_name_type(self, name_type: TypeForm[_T1], component_type: TypeForm[_T2]) -> Iterator[tuple[_T1, type[_T2]]]:
"""Iterate over all of an entities component keys with a specific (name_type, component_type) combination.

.. versionadded:: 3.0

.. deprecated:: 3.1
This method has been deprecated. Iterate over items instead.
"""
# Naive implementation until I feel like optimizing it
for key in self:
if not isinstance(key, tuple):
continue
key_name, key_component = key
if key_component is component_type and isinstance(key_name, name_type):
yield key_name, key_component
yield key_name, key_component # type: ignore[unused-ignore] # Too complex for PyLance, deprecated anyways

@overload
def __ior__(self, value: SupportsKeysAndGetItem[ComponentKey[Any], Any]) -> Self: ...
Expand Down Expand Up @@ -544,7 +542,7 @@
except KeyError:
return default # type: ignore[return-value] # https://github.com/python/mypy/issues/3737

def setdefault(self, __key: ComponentKey[T], __default: T, /) -> T:
def setdefault(self, __key: ComponentKey[T], __default: T, /) -> T: # type: ignore[override] # Does not allow None
"""Assign a default value if a component is missing, then returns the current value."""
try:
return self[__key]
Expand Down Expand Up @@ -1032,14 +1030,14 @@
"""Access relations for this component key as a `{target: component}` dict-like object."""
return EntityComponentRelationMapping(self.entity, key, self.traverse)

def __setitem__(self, __key: ComponentKey[T], __values: Mapping[Entity, object], /) -> None:
def __setitem__(self, __key: ComponentKey[T], __values: Mapping[Entity, T], /) -> None:
"""Redefine the component relations for this entity.

..versionadded:: 4.2.0
"""
if isinstance(__values, EntityComponentRelationMapping) and __values.entity is self.entity:
return
mapping: EntityComponentRelationMapping[object] = self[__key]
mapping: EntityComponentRelationMapping[T] = self[__key]
mapping.clear()
for target, component in __values.items():
mapping[target] = component
Expand Down
6 changes: 3 additions & 3 deletions tcod/ecs/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ def _defaultdict_of_dict() -> defaultdict[_T1, dict[_T2, _T3]]:


def _components_by_entity_from(
by_type: defaultdict[ComponentKey[object], dict[Entity, Any]],
) -> defaultdict[Entity, dict[ComponentKey[object], Any]]:
by_type: defaultdict[ComponentKey[_T1], dict[Entity, _T1]],
) -> defaultdict[Entity, dict[ComponentKey[_T1], _T1]]:
"""Return the component lookup table from the components sparse-set."""
by_entity: defaultdict[Entity, dict[ComponentKey[object], Any]] = defaultdict(dict)
by_entity: defaultdict[Entity, dict[ComponentKey[_T1], _T1]] = defaultdict(dict)
for component_key, components in by_type.items():
for entity, component in components.items():
by_entity[entity][component_key] = component
Expand Down
6 changes: 3 additions & 3 deletions tcod/ecs/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

import sys
import types
from typing import TYPE_CHECKING, Any, Tuple, Type, TypeVar, Union
from typing import TYPE_CHECKING, Any, Tuple, TypeVar, Union

from typing_extensions import TypeAlias
from typing_extensions import TypeAlias, TypeForm

Check failure on line 9 in tcod/ecs/typing.py

View workflow job for this annotation

GitHub Actions / mypy (3.12)

Module "typing_extensions" has no attribute "TypeForm"

Check failure on line 9 in tcod/ecs/typing.py

View workflow job for this annotation

GitHub Actions / mypy (3.12)

Module "typing_extensions" has no attribute "TypeForm"

if TYPE_CHECKING:
from tcod.ecs.entity import Entity
Expand All @@ -22,7 +22,7 @@

_T = TypeVar("_T")

ComponentKey: TypeAlias = Union[Type[_T], Tuple[object, Type[_T]]]
ComponentKey: TypeAlias = Union[TypeForm[_T], Tuple[object, TypeForm[_T]]]
"""ComponentKey is plain `type` or tuple `(tag, type)`."""

_RelationTargetLookup: TypeAlias = Union[Entity, EllipsisType]
Expand Down
Loading