Skip to content

GufeTokenizables cannot contain a dictionary with other GufeTokenizables as keys #714

@ianmkenney

Description

@ianmkenney

Defining and instantiating a GufeTokenizable that contains a dictionary whose keys are also GufeTokenizable instances raises a TypeError. Since GufeTokenizable instances are unique and hashable, this should be supported. Additionally, such a data-structure has value in mitigating risk of stale GufeKey instances within a GufeTokenizable on deserialization (see the transformation_results_map attribute of AlchemicalArchive in #687).

from gufe.tokenization import GufeTokenizable

class Foo(GufeTokenizable):

    def __init__(self, data = None):
        self.data = data

    @staticmethod
    def _defaults(): return {}

    def _to_dict(self): return {"data": self.data}

    @classmethod
    def _from_dict(cls, dct): return cls(**dct)


if __name__ == "__main__":
    gt_attr = Foo(data=Foo())
    dct_attr_gt_value = Foo(data={"some_key": Foo()})
    dct_attr_gt_key = Foo(data={Foo(): "some_value"})
../env/bin/python gt_as_keys.py 
Traceback (most recent call last):
  File "[...]/gufe/network/gt_as_keys.py", line 20, in <module>
    dct_attr_gt_key = Foo(data={Foo(): "some_value"})
  File "[...]/gufe/gufe/tokenization.py", line 78, in __call__
    key = instance.key
          ^^^^^^^^^^^^
  File "[...]/gufe/gufe/tokenization.py", line 424, in key
    token = self._gufe_tokenize()
  File "[...]/gufe/gufe/tokenization.py", line 356, in _gufe_tokenize
    return tokenize(self)
  File "[...]/gufe/gufe/tokenization.py", line 1240, in tokenize
    dumped = json.dumps(
        obj.to_keyed_dict(include_defaults=False),
        sort_keys=True,
        cls=JSON_HANDLER.encoder,
    )
  File "[...]/gufe/env/lib/python3.13/json/__init__.py", line 242, in dumps
    **kw).encode(obj)
          ~~~~~~^^^^^
  File "[...]/gufe/env/lib/python3.13/json/encoder.py", line 202, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "[...]/gufe/env/lib/python3.13/json/encoder.py", line 263, in iterencode
    return _iterencode(o, 0)
TypeError: keys must be str, int, float, bool or None, not Foo

Metadata

Metadata

Assignees

Type

No type

Projects

Status

No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions