-
Notifications
You must be signed in to change notification settings - Fork 382
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
Add pickle support to ReadOnly{Dict,List} #508
Conversation
How about removing
There may come up even more difficulties. |
The config shouldn't be modified, so I am sympathetic to the intended purpose of If the only downside is that type-checking against The lack of JSON/YAML support is a downside I hadn't considered. I think you can get around this by doing |
I do not say, that the config should be modified. While the advantages of this feature are nice, but not necessary, the disadvantages, that are known until now are terrible: Implicit changing the type and no support to dump the config. |
Well this turns out to make more trouble than expected. In the original discussion with @thequilo we decided that it was a priority to keep type checking intact. @AdamGleave you are of course right that type checking against explicit types it bad practice anyway. Checking against
|
@AdamGleave by the way python 2 support has already been dropped, so no need to write any compatibility code anymore :) |
For me Breaking type checking is sad, but seems to me like the least-bad evil. Inheriting from built-in types have a lot of pitfalls anyway, e.g. this gotcha. It should probably be announced as a breaking change in the changelist though.
I think @boeddeker meant that just calling e.g. |
When you dump custom types with yaml, you get !!python/object/new:__main__.ReadOnlyDict
dictitems:
'1': 2
state:
message: This ReadOnlyDict is read-only! or when you follow the advice from [1] you can not dump custom types. I tested now also json. I didn't know that it does an
[1] https://github.com/yaml/pyyaml/wiki/PyYAML-yaml.load(input)-Deprecation |
My suggestion would be that we specify the requirements that we have towards serializability of the config objects clearly using some tests. Then we can search more specifically for possible solutions. |
How about this: class ReadOnlyDict(dict):
def __init__(self, container, _message=None):
super().__init__(container)
self._message = _message or 'This dict is read-only!'
def _readonly(self, *args, **kwargs):
raise SacredError(
self.message,
filter_traceback='always'
)
def __reduce__(self):
return ReadOnlyDict, (dict(self.items()), self._message)
clear = _readonly
pop = _readonly
popitem = _readonly
setdefault = _readonly
update = _readonly
__setitem__ = _readonly
__delitem__ = _readonly This can be serialized/deserialized with |
There are always serializers that check the type and don't use isinstance.
|
@Qwlouse this seems to be a good trade-off of the different requirements. It's a shame YAML doesn't support it out the box but |
@AdamGleave : It is correct, that YAML does not support this. |
Wouldn't |
This is a viable workaround, but I think it has some drawbacks as a solution. You obviously lose the benefit of read-only dictionaries/lists. Serialization also seems like a very common use case, so I'd strongly advocate for making it work out of the box, without setting obscure flags. If that's not possible, then I'd suggest at least having an informative error message. In my case, it was quite hard to even identify that Sacred was the problem ( |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
@JarnoRFB: To check that I'm understanding this thread right (and that this hasn't changed over the past few months), would the Sacred maintainers likely accept a variant of this PR that uses |
Closes #499.
Initially I tried to add
pickle
support using__getstate__
and__setstate
. However,pickle
, seems to special-case built-in container types: my__setstate__
method never even got called inReadOnlyDict
. Accordingly I decided to switch to a proxy style, where we are wrapping a dict/list object. This is similar to the MappingProxyType, which we could probably replaceReadOnlyDict
with once Python 2.7 support is dropped (it's only available in Python 3.3+).