Add generic type parameters to Agent, AgentSet, and Model#2885
Add generic type parameters to Agent, AgentSet, and Model#2885
Conversation
This comment was marked as off-topic.
This comment was marked as off-topic.
|
Thanks for tackling this issue, improved type hints are definitely useful. The implementation looks solid, but I wanted to mention: since we recently dropped Python 3.11 support and now require 3.12+, we can actually use the newer PEP 695 syntax instead of the Python 3.12 introduced cleaner syntax for generics that eliminates the need for the conditional Instead of: if TYPE_CHECKING:
M = TypeVar("M", bound=Model)
A = TypeVar("A", bound="Agent")
else:
M = TypeVar("M")
A = TypeVar("A")
class Agent(Generic[M]): # noqa: UP046
def __init__(self, model: M, *args, **kwargs) -> None:
self.model: M = modelWe can now write: class Agent[M: Model]:
def __init__(self, model: M, *args, **kwargs) -> None:
self.model: M = modelSame goes for class AgentSet[A: Agent](MutableSet[A], Sequence[A]):
# ...
@classmethod
def create_agents[T: Agent](cls: type[T], model: M, n: int, *args, **kwargs) -> AgentSet[T]:
# ...The PEP 695 syntax is more readable, eliminates the runtime/type-checking split, and is the idiomatic way to do this in Python 3.12+. The Would you be up for refactoring this to use the new syntax? |
|
@EwoutH Thanks, i have made the following changes |
|
@EwoutH incase you missed the changes, could you look upon the changes |
| def create_agents[T: Agent]( | ||
| cls: type[T], model: Model, n: int, *args, **kwargs | ||
| ) -> AgentSet[T]: |
There was a problem hiding this comment.
Why is T used here for Agent? Wouldn't A be more logical?
Please motivate first. But if you agree:
| def create_agents[T: Agent]( | |
| cls: type[T], model: Model, n: int, *args, **kwargs | |
| ) -> AgentSet[T]: | |
| def create_agents[A: Agent]( | |
| cls: type[A], model: Model, n: int, *args, **kwargs | |
| ) -> AgentSet[A]: |
There was a problem hiding this comment.
In my understanding of typing, T is just the common default to use. But I am by no means an expert yet on type hinting in python.
129f3c2 to
638dc87
Compare
|
@SiddharthBansal007 sorry for the late review. I've a few more (minor) comments, can you address them? Please don't adopt them without thinking, but critically check. |
for more information, see https://pre-commit.ci
|
@EwoutH, I picked this up and made a bunch of changes. Can you check to see if it's good to go at this point? I'd like to get this merged. |
Co-authored-by: Ewout ter Hoeven <[email protected]>
Co-authored-by: Ewout ter Hoeven <[email protected]>
for more information, see https://pre-commit.ci
|
@EwoutH, I addressed your comments. I think this is ready for now. I want to guard against scope creep, so as long as these changes are fine, I suggest we move forward. From my own first impressions, some type warnings seem to be gone when using this PR. |
EwoutH
left a comment
There was a problem hiding this comment.
Looks good to me! @SiddharthBansal007 thanks for the initial PR and @quaquel for landing it.
Summary
Implements PEP 695 generic typing for
Agent,AgentSet, andModelclasses to enable static type checkers to preserve concrete agent and model types throughout the codebase.Motive
Previously, type checkers could not infer specific agent or model types:
model.agentsreturned untypedAgentSet[Agent]instead of the specific agent typeagent.modelreturned genericModelinstead of the concrete model typeAgentSetlost type informationThis made it difficult to catch type errors at development time and reduced IDE autocomplete effectiveness.
Implementation
MtoAgent[M: Model]to track the specific model typeAtoModel[A: Agent]to track the specific agent typeAtoAgentSet[A: Agent]for type-safe collectionsfilter_func: Callable[[A], bool],key: Callable[[A], Any])@overloaddecorators toAgentSet.__getitem__to distinguish between int and slice indexing_agents: dict[A, None],_agents_by_type: dict[type[A], AgentSet[A]])Usage Examples
Additional Notes
Agent[M: Model]andModel[A: Agent]create a circular type bound dependency, which is acceptable for this use casecreate_agentsuses independent type variableTto support subclass creation