-
Notifications
You must be signed in to change notification settings - Fork 137
Description
Description
This is in MetaType, but AFAICT only ops ever have props
pytensor/pytensor/graph/utils.py
Lines 193 to 234 in 17748b7
props = dct.get("__props__", None) | |
if props is not None: | |
if not isinstance(props, tuple): | |
raise TypeError("__props__ has to be a tuple") | |
if not all(isinstance(p, str) for p in props): | |
raise TypeError("elements of __props__ have to be strings") | |
def _props(self): | |
""" | |
Tuple of properties of all attributes | |
""" | |
return tuple(getattr(self, a) for a in props) | |
dct["_props"] = _props | |
def _props_dict(self): | |
"""This return a dict of all ``__props__`` key-> value. | |
This is useful in optimization to swap op that should have the | |
same props. This help detect error that the new op have at | |
least all the original props. | |
""" | |
return {a: getattr(self, a) for a in props} | |
dct["_props_dict"] = _props_dict | |
if "__hash__" not in dct: | |
def __hash__(self): | |
return hash((type(self), tuple(getattr(self, a) for a in props))) | |
dct["__hash__"] = __hash__ | |
if "__eq__" not in dct: | |
def __eq__(self, other): | |
return type(self) is type(other) and tuple( | |
getattr(self, a) for a in props | |
) == tuple(getattr(other, a) for a in props) | |
dct["__eq__"] = __eq__ |
Generating them dynamically like this means linters / mypy don't believe in op._props()
or op._props_dict()
. I don't know why this has to be implemented as methods in the MetaClass instead of just in the Op baseclass. Would be great if someone gave a try at it. It also means we could probably get rid of the whole MetaType class, since the only other thing is a string convenience, which definitely need not be defined there.
May also be worth investigating if we can use frozen dataclasses
for Ops
and automate the props logic (see aesara discussion, but that needs not be done together with addressing the main issue here.