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

Fixes for #302 and #310 #311

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 49 additions & 13 deletions apptools/persistence/state_pickler.py
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,31 @@ class StateSetter:
that when it sets the state.
"""

def __init__(self):
def __init__(self, ignore=None, first=None, last=None):
"""Sets the state of the object.

Parameters
----------

- ignore : `list(str)`

The list of attributes specified in this list are ignored
and the state of these attributes are not set (this excludes
the ones specified in `first` and `last`). If one specifies
a '*' then all attributes are ignored except the ones
specified in `first` and `last`.

- first : `list(str)`

The list of attributes specified in this list are set first (in
order), before any other attributes are set.

- last : `list(str)`

The list of attributes specified in this list are set last (in
order), after all other attributes are set.

"""
# Stores the ids of instances already done.
self._instance_ids = []
self.type_map = {
Expand All @@ -706,6 +730,9 @@ def __init__(self):
StateList: self._do_list,
StateDict: self._do_dict,
}
self.ignore = ignore
self.first = first
self.last = last

def set(self, obj, state, ignore=None, first=None, last=None):
"""Sets the state of the object.
Expand Down Expand Up @@ -760,15 +787,15 @@ def set(self, obj, state, ignore=None, first=None, last=None):

self._register(obj)

# This wierdness is needed since the state's own `keys` might
# This weirdness is needed since the state's own `keys` might
# be set to something else.
state_keys = list(dict.keys(state))
state_keys.remove("__metadata__")

if first is None:
first = []
if last is None:
last = []
# fallback to instance default
first = first or self.first or []
last = last or self.last or []
ignore = ignore or self.ignore or []

# Remove all the ignored keys.
if ignore:
Expand All @@ -778,7 +805,7 @@ def set(self, obj, state, ignore=None, first=None, last=None):
for name in ignore:
try:
state_keys.remove(name)
except KeyError:
except ValueError:
pass

# Do the `first` attributes.
Expand Down Expand Up @@ -915,20 +942,29 @@ def _do_list(self, obj, state):
if not self._has_instance(state[i]):
obj[i] = self._get_pure(state[i])
elif isinstance(state[i], tuple):
obj[i] = self._do_tuple(state[i])
obj[i] = self._do_tuple(obj[i], state[i])
else:
self._do_object(obj[i], state[i])
else:
raise StateSetterError(
"Cannot set state of list of incorrect size."
)
# dynamically increase list so restoring works
obj.clear()
for i in range(len(state)):
if not self._has_instance(state[i]):
new_item = self._get_pure(state[i])
elif isinstance(state[i], tuple):
new_item = self._do_tuple(obj, state[i])
else:
new_item = create_instance(state[i])
self._do_object(new_item, state[i])
obj.append(new_item)

def _do_dict(self, obj, state):
obj.clear()
for key, value in state.items():
if not self._has_instance(value):
obj[key] = self._get_pure(value)
elif isinstance(value, tuple):
obj[key] = self._do_tuple(value)
obj[key] = self._do_tuple(obj, value)
else:
self._do_object(obj[key], value)

Expand Down Expand Up @@ -1001,7 +1037,7 @@ def get_state(obj):


def set_state(obj, state, ignore=None, first=None, last=None):
StateSetter().set(obj, state, ignore, first, last)
StateSetter(ignore, first, last).set(obj, state, ignore, first, last)


set_state.__doc__ = StateSetter.set.__doc__
Expand Down
Loading