From 23f50707a703c12bd26adfeafc363f913b24b522 Mon Sep 17 00:00:00 2001 From: Daniel McCoy Stephenson Date: Thu, 10 Sep 2026 01:12:47 -0600 Subject: [PATCH] Write the ideas file with "w" and an explicit utf-8 encoding Co-Authored-By: Claude Opus 5 (1M context) --- src/ideaCollisionGenerator.py | 2 +- tests/test_ideaCollisionGenerator.py | 46 ++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/ideaCollisionGenerator.py b/src/ideaCollisionGenerator.py index 8d3de86..406ac5f 100644 --- a/src/ideaCollisionGenerator.py +++ b/src/ideaCollisionGenerator.py @@ -53,6 +53,6 @@ def writeToFile(self): filename = "ideas/ideas-" + timestamp + ".txt" # write idea to file - with open(filename, "a") as f: + with open(filename, "w", encoding="utf-8") as f: for i in range(len(self.pairs)): f.write(str(self.pairs[i]) + ": " + self.ideas[i] + "\n") \ No newline at end of file diff --git a/tests/test_ideaCollisionGenerator.py b/tests/test_ideaCollisionGenerator.py index 93e8c77..9d8cbf2 100644 --- a/tests/test_ideaCollisionGenerator.py +++ b/tests/test_ideaCollisionGenerator.py @@ -154,6 +154,52 @@ def testCreatesIdeasDirectoryRelativeToWorkingDirectory(self): generator.writeToFile() self.assertTrue(os.path.isdir("ideas")) + def testSameTimestampReplacesRatherThanAppends(self): + # the timestamp has one-second resolution, so two runs can land on the + # same filename; the second one replaces the first + generator = IdeaCollisionGenerator() + generator.pairs = [["a", "b"]] + generator.ideas = ["first"] + + frozenClock = mock.Mock() + frozenClock.datetime.now.return_value.strftime.return_value = "frozen" + with mock.patch("ideaCollisionGenerator.datetime", frozenClock): + generator.writeToFile() + + second = IdeaCollisionGenerator() + second.pairs = [["c", "d"]] + second.ideas = ["second"] + second.writeToFile() + + self.assertEqual(os.listdir("ideas"), ["ideas-frozen.txt"]) + with open(os.path.join("ideas", "ideas-frozen.txt")) as f: + self.assertEqual(f.readlines(), ["['c', 'd']: second\n"]) + + def testOutputFileIsOpenedAsUtf8(self): + # the written bytes are the same under the platform default on every + # machine the tests run on, so the encoding is observed on the call + generator = IdeaCollisionGenerator() + generator.pairs = [["café", "b"]] + generator.ideas = ["résumé"] + + realOpen = open + recorded = {} + + def recordingOpen(path, *args, **kwargs): + recorded["args"] = args + recorded["kwargs"] = kwargs + return realOpen(path, *args, **kwargs) + + with mock.patch("builtins.open", recordingOpen): + generator.writeToFile() + + self.assertEqual(recorded["args"], ("w",)) + self.assertEqual(recorded["kwargs"], {"encoding": "utf-8"}) + + written = os.listdir("ideas")[0] + with open(os.path.join("ideas", written), "rb") as f: + self.assertEqual(f.read().decode("utf-8"), "['café', 'b']: résumé\n") + def testFilenameIsTimestamped(self): generator = IdeaCollisionGenerator() generator.pairs = [["a", "b"]]