From c62e5d7351af33cb10de72eb06e5130ef9d3724c Mon Sep 17 00:00:00 2001 From: nyanpasu64 <nyanpasu64@tuta.io> Date: Sun, 13 Jun 2021 19:53:54 -0700 Subject: [PATCH] Construct new YAML serializer object on every load/save operation Not sure if this is a good idea worth keeping. It may or may not fix a bug I've seen months ago. In return, it introduces complexity and brittleness into my code, and could stop working in a future ruamel.yaml update. Also `pip install` doesn't pin the exact ruamel.yaml version (accepting higher versions that could break my code), only `poetry install` pins an exact version. --- CHANGELOG.md | 1 + corrscope/config.py | 41 ++++++++++++++++++++++++++++++++++------- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c0b31c..e8d2b4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### Changelog - Update NumPy so `poetry install` on Python 3.8+ won't build NumPy from source (#371) +- Fix possible bug where loading a corrupted file would cause future loading operations to fail (#???) - Fix longstanding crash when prefs.yaml is corrupted, reset settings instead (#377) - Atomically save prefs.yaml to prevent file corruption (#377) diff --git a/corrscope/config.py b/corrscope/config.py index 2b42f3c..d5b14ac 100644 --- a/corrscope/config.py +++ b/corrscope/config.py @@ -119,15 +119,42 @@ class NoAliasRepresenter(RoundTripRepresenter): return super().ignore_aliases(data) -yaml = MyYAML() -yaml.width = float("inf") +class yaml: + """ + Using a MyYAML object to load corrupted YAML files used to corrupt the object, + causing it to crash when trying to load future files. + I don't remember what kinds of YAML files reproduce the issue, + nor whether the bug still works. + However, making yaml.load()/yaml.dump() construct a new MyYAML object each time + means that even if the MyYAML object gets corrupted, + it's discarded and doesn't affect future yaml.load()/yaml.dump() operations. + """ -# Default typ='roundtrip' creates 'ruamel.yaml.comments.CommentedMap' instead of dict. -# Is isinstance(CommentedMap, dict)? IDK -assert yaml.Representer == RoundTripRepresenter -yaml.Representer = NoAliasRepresenter + @staticmethod + def _get_yaml(): + yaml = MyYAML() + yaml.width = float("inf") -_yaml_loadable = yaml_object(yaml) + # Default typ='roundtrip' creates 'ruamel.yaml.comments.CommentedMap' instead of dict. + # Is isinstance(CommentedMap, dict)? IDK + assert yaml.Representer == RoundTripRepresenter + yaml.Representer = NoAliasRepresenter + + return yaml + + @staticmethod + def load(*args, **kwargs): + return yaml._get_yaml().load(*args, **kwargs) + + @staticmethod + def dump(*args, **kwargs): + return yaml._get_yaml().dump(*args, **kwargs) + + +# This code is *very* hacky: +# calling _yaml_loadable(FooConfig) mutates the MyYAML.Representer and +# MyYAML.Constructor classes, to register FooConfig as serializable as YAML. +_yaml_loadable = yaml_object(MyYAML()) """