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())
 
 
 """