Opened 4 years ago

Closed 4 years ago

Last modified 4 years ago

#5222 closed enhancement (not a bug)

core/state.py: Allow NamedTuples in bundle data

Reported by: Zach Pearson Owned by: Zach Pearson
Priority: low Milestone: Ideas
Component: Sessions Version:
Keywords: Cc: Greg Couch
Blocked By: Blocking:
Notify when closed: Platform: all
Project: ChimeraX

Description

Would be good to have some way to register NamedTuples with _container_primitives from src/core/state.py. NamedTuples are instances of tuple.

Change History (6)

comment:1 by Eric Pettersen, 4 years ago

Cc: Greg Couch added

comment:2 by Greg Couch, 4 years ago

You should not need to do this if the named tuple class is in the bundle's bundle_api's get_class method.

comment:3 by Zach Pearson, 4 years ago

I see, OK -- thanks!

We might be able to do a clever trick to simplify the Bundle API a litte here by using Python's inspect library.

To get a list of all the classes a module exposes publicly (i.e. that don't start with underscores) we can have a line:

[def_tuple for def_tuple in inspect.getmembers(sys.modules[__name__]) if inspect.isclass(def_tuple[1])]

With that in mind, in get_class:

def get_class(class_name):
    classes = {}
    for cls in [def_tuple for def_tuple in inspect.getmembers(sys.modules[__name__]) if inspect.isclass(def_tuple[1])]:
        classes[cls[0]] = cls[1]
    return classes.get(class_name, None)

If we made this the default behavior I wonder how many bundles would have to bother implementing get_class.

Last edited 4 years ago by Zach Pearson (previous) (diff)

comment:4 by Greg Couch, 4 years ago

It would convenient, but no. The classes exported by a bundle via get_class have to be supported forever or else sessions can not restore. That needs to be an explicit API decision by the bundle writer, not automatically inferred.

And in the case of named tuples, I'd recommend not putting them in get_class. The more the session data can be make of just primitive data, the better. If there are no objects in the saved state data, then the FinalizedState hack can be used to speed up the saving and restoring of data because the data does not need to be scanned, and copied, to handle objects.

Last edited 4 years ago by Greg Couch (previous) (diff)

comment:5 by Zach Pearson, 4 years ago

Resolution: not a bug
Status: assignedclosed

OK, that makes sense. The only other suggestion I'd make would be to then use a class attribute that lists the supported classes and check class requests against it, but I don't think that's enough of an improvement over the status quo to put work into doing it.

My current workaround is to unpack the data into a regular tuple and repack it into the NamedTuple when the session gets restored -- but now that I know about the FinalizedState speed-up you mentioned that'll be a more deliberate decision in the future; I thought of it as more of a hack previously.

comment:6 by Greg Couch, 4 years ago

(in reverse order)

FinalizedState is a hack. I wish it weren't needed, but it makes saving and restoring atomic data reasonably quick as opposed to intolerably slow.

Your workaround is the right thing to do. It's same thing that needs to be done when reading/writing JSON from richer data structures.

I'm not sure how much we can standardize how get_class works. For example, not all classes saved in sessions derive from chimerax.core.state.State. See Session.register_snapshot_methods and bundles/graphics/src/gsession.py. And a bundle writer can use a class attribute if they wish.

Note: See TracTickets for help on using tickets.