Skip to content
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

The use_state branch does not handle when __reduce__ returns a string #76

Closed
liamhuber opened this issue Jan 25, 2024 · 0 comments · Fixed by #77
Closed

The use_state branch does not handle when __reduce__ returns a string #76

liamhuber opened this issue Jan 25, 2024 · 0 comments · Fixed by #77

Comments

@liamhuber
Copy link
Contributor

E.g. for the singleton pattern, as discussed in the pickle docs for __reduce__

MWE:

from abc import ABCMeta

import h5io

class Singleton(ABCMeta):
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]

class MySingleton(metaclass=Singleton):
    def __reduce__(self):
        return "my_global"  # The associated global variable

my_global = MySingleton()
my_global.data = "something"

h5io.write_hdf5(
    fname="stuff.hdf5",
    data=my_global,
    overwrite=True,
    use_json=False,
    use_state=True,
)

reloaded = h5io.read_hdf5(fname="stuff.hdf5")

assert reloaded is my_global
assert reloaded.data == "something"

This should re-import the singleton with its saved state, but instead raises an error ending in:

...
File ~/work/pyiron/h5io/h5io/_h5io.py:378, in _triage_write(key, value, root, comp_kw, where, cleanup_data, slash, title, use_json, use_state)
    366     reconstructor, _, state, *additional = reduced
    367 # For plain objects defining a simple __getstate__ python uses a
    368 # default reconstruction function defined in the copyreg module, if
    369 # an object wants to be reconstructed in any other way, we don't
   (...)
    374 # reconstruction of the object (documented in the pickle module)
    375 # that we don't implement currently in the _triage_read function
    376 is_custom = (
    377     reconstructor is not type(value)
--> 378     and reconstructor.__module__ != "copyreg"
    379 )
    380 if is_custom or len(additional) != 0:
    381     raise TypeError(
    382         f"Can't write {repr(value)} at location {key}:\n"
    383         f"Class {class_type} defines custom reconstructor."
    384     )

AttributeError: 'str' object has no attribute '__module__'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant