diff options
| author | historia <historiavg@proton.me> | 2026-08-27 18:41:10 -0400 |
|---|---|---|
| committer | historia <historiavg@proton.me> | 2026-08-27 18:41:10 -0400 |
| commit | b6795046bf20023fd7b2e083ead20e7362f0c0d7 (patch) | |
| tree | 20c8fd1cde5ed7fbb2c630e8250af098f547be05 /app/tests | |
| parent | 0047a875d0a969005f3cea3df18de909d285f910 (diff) | |
| download | tts-audiobook-generator-b6795046bf20023fd7b2e083ead20e7362f0c0d7.tar.gz | |
feat: simply generate audiobooks menu, move more config to settings menu
Diffstat (limited to 'app/tests')
| -rw-r--r-- | app/tests/test_hub.py | 224 |
1 files changed, 154 insertions, 70 deletions
diff --git a/app/tests/test_hub.py b/app/tests/test_hub.py index fd22a4e..3550f5b 100644 --- a/app/tests/test_hub.py +++ b/app/tests/test_hub.py @@ -370,10 +370,14 @@ class HubMenuTests(unittest.TestCase): self.assertIn("6. Generated audiobooks (m4b, mp3, etc.) will " "output here:", text) # The three folder paths are their own indented, white-bold - # ("input") rows; the numbered steps start at the margin. - self.assertIn(([(str(hub.BOOKS_FOLDER), "input")], 1), items) + # ("input") rows; the numbered steps start at the margin. They + # resolve live from the converter module, so a Settings change + # this session is reflected. + self.assertIn(([(str(hub.converter_mod.BOOKS_FOLDER), "input")], 1), + items) self.assertIn(([(str(hub.common.VOICES_DIR), "input")], 1), items) - self.assertIn(([(str(hub.AUDIOBOOKS_FOLDER), "input")], 1), items) + self.assertIn(([(str(hub.converter_mod.AUDIOBOOKS_FOLDER), "input")], + 1), items) self.assertEqual(items[0][1], 0) @@ -812,16 +816,16 @@ class ConvertFlowTests(unittest.TestCase): # Keys shared by every backend entry; a "-remote" backend's other # option keys are namespaced under "<entry>." in the form dict # (mirroring hub.py), so _form_values maps them automatically. - _COMMON_KEYS = frozenset(("backend", "output_format", "language", - "speed", "single_file", "debug", - "stop_and_exit")) + _COMMON_KEYS = frozenset(("backend", "single_file")) def _form_values(self, **overrides): - """A fully-populated form result, with sensible defaults.""" - values = {"output_format": "m4b", "language": "English", - "speed": "1.0", - "single_file": False, "debug": False, - "stop_and_exit": True} + """A fully-populated form result, with sensible defaults. + + Output format, language, speed, debug, and stop-and-exit are no + longer form fields: they live in config.py (Settings) and reach + the run kwargs via _common_kwargs(). + """ + values = {"single_file": False} values.update(overrides) backend = values.get("backend") or "" if backend.endswith("-remote"): @@ -897,13 +901,16 @@ class ConvertFlowTests(unittest.TestCase): self._patch_remote( [{"id": "higgs", "family": "higgs_audio_tts", "task": "tts"}], voices=["narrator"]) - # Pin the seeded toggle so this test does not depend on the user's - # saved STOP_SERVER_AND_EXIT value in config.py. + # Pin the config settings the common kwargs are built from, so + # this test does not depend on the user's saved config.py values. with patch.object(hub.config, "STOP_SERVER_AND_EXIT", True), \ + patch.object(hub.config, "AUDIO_FORMAT", "m4b"), \ + patch.object(hub.config, "LANGUAGE", "English"), \ + patch.object(hub.config, "SPEED", 1.25), \ + patch.object(hub.config, "DEBUG", False), \ patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""): self._answer_form(backend="audiocpp-remote", model_id="higgs", - audiocpp_voice="narrator", instructions="", - speed="1.5") + audiocpp_voice="narrator", instructions="") cmd = self._convert( None, [self._remote("audiocpp", "audio.cpp")]) self.assertEqual(cmd[0], "convert") @@ -913,10 +920,14 @@ class ConvertFlowTests(unittest.TestCase): self.assertEqual(kwargs["voice"], "narrator") self.assertIsNone(kwargs["instructions"]) self.assertEqual(kwargs["api_url"], "http://audiocpp.local:8080") + # The output settings come from config (the Settings menu), not + # the form. self.assertEqual(kwargs["output_format"], "m4b") - self.assertEqual(kwargs["speed"], 1.5) + self.assertEqual(kwargs["language"], "English") + self.assertEqual(kwargs["speed"], 1.25) self.assertFalse(kwargs["single_file"]) self.assertFalse(kwargs["debug"]) + self.assertTrue(kwargs["stop_and_exit"]) # One form, not a cascade of menus/editors. self.assertEqual(len(self.tui.forms_seen), 1) title, fields, form_kwargs = self.tui.forms_seen[0] @@ -926,15 +937,9 @@ class ConvertFlowTests(unittest.TestCase): "audiocpp-remote.audiocpp_voice", "audiocpp-remote.instructions", "audiocpp-remote.request_options", - "output_format", "language", - "speed", "single_file", "debug", "stop_and_exit"]) + "single_file"]) self.assertEqual(form_kwargs["buttons"], ("Generate!", "Cancel")) self.assertTrue(form_kwargs["start_on_buttons"]) - # The stop-and-exit toggle ships on by default. - stop_field = self._field("stop_and_exit") - self.assertEqual(stop_field["kind"], "bool") - self.assertTrue(stop_field["value"]) - self.assertTrue(cmd[2]["stop_and_exit"]) # The backend field offers the remote entry under a [remote] label. self.assertEqual(fields[0]["choices"], [("audio.cpp [remote]", "audiocpp-remote")]) @@ -1353,14 +1358,17 @@ class ConvertFlowTests(unittest.TestCase): self.assertIn("KEY=VALUE", help_text) self.assertIn("emotion=neutral", help_text) - def test_language_passes_through_normalized(self): + def test_language_passes_through_from_config(self): + # The Settings Language setting travels on the run kwargs as-is; + # the converter normalizes it (short codes included). with patch.object(hub.qwen_backend, "QWEN_SPEAKERS", ["Vivian"]), \ - patch.object(hub.config, "SPEAKER", "Vivian"): + patch.object(hub.config, "SPEAKER", "Vivian"), \ + patch.object(hub.config, "LANGUAGE", "en"): self._answer_form(backend="qwen", mode="custom", - speaker="Vivian", clone="", language="en") + speaker="Vivian", clone="") cmd = self._convert(None, [self._ready("qwen", "qwen-tts")]) - self.assertEqual(cmd[2]["language"], "English") + self.assertEqual(cmd[2]["language"], "en") def test_audiocpp_remote_unreachable_models_flash_and_abort(self): self._patch_remote(None) # endpoint did not answer valid JSON @@ -1472,9 +1480,7 @@ class ConvertFlowTests(unittest.TestCase): voices=["narrator"]) statuses = [self._ready("audiocpp", "audio.cpp"), self._remote("audiocpp", "audio.cpp")] - common = {"output_format": "m4b", "speed": "1.0", - "single_file": False, "debug": False, - "stop_and_exit": True} + common = {"single_file": False} with tempfile.TemporaryDirectory() as td: root = Path(td) (root / "server.json").write_text(json.dumps({ @@ -1523,17 +1529,18 @@ class ConvertFlowTests(unittest.TestCase): self.assertEqual(cmd[2]["api_url"], "http://10.0.0.5:8080") # ------------------------------------------------------------------ - # common fields: output format, speed, single-file, debug + # common fields: the per-run combine-all-chapters toggle # ------------------------------------------------------------------ def test_common_fields_hide_combine_for_m4b(self): + # The toggle's visibility tracks the configured output format + # (the Settings menu's Audio format), not a form field. fields = hub._common_fields() - fmt = next(f for f in fields if f["key"] == "output_format") single = next(f for f in fields if f["key"] == "single_file") - fmt["value"] = "m4b" - self.assertFalse(single["visible"](fields)) - fmt["value"] = "mp3" - self.assertTrue(single["visible"](fields)) + with patch.object(hub.config, "AUDIO_FORMAT", "m4b"): + self.assertFalse(single["visible"](fields)) + with patch.object(hub.config, "AUDIO_FORMAT", "mp3"): + self.assertTrue(single["visible"](fields)) # ------------------------------------------------------------------ # qwen: model picker (Base / CustomVoice / VoiceDesign) @@ -1566,10 +1573,7 @@ class ConvertFlowTests(unittest.TestCase): fields = self.tui.forms_seen[0][1] self.assertEqual([f["key"] for f in fields], ["backend", "mode", "speaker", "clone", - "qwen_instructions", - "output_format", "language", "speed", - "single_file", "debug", - "stop_and_exit"]) + "qwen_instructions", "single_file"]) mode_field = self._field("mode") self.assertEqual(mode_field["choices"], [("CustomVoice (built-in voices)", "custom"), @@ -1654,9 +1658,6 @@ class ConvertFlowTests(unittest.TestCase): # faster voices are server-side clone references. self.assertEqual(self._field("faster_voice")["label"], "Voice to clone") - # Language is server-owned on faster: the per-run field is hidden. - fields = self.tui.forms_seen[0][1] - self.assertFalse(self._field("language")["visible"](fields)) def test_faster_local_still_lists_voices_json(self): with tempfile.TemporaryDirectory() as td: @@ -1704,16 +1705,15 @@ class ConvertFlowTests(unittest.TestCase): self.assertIs(self.nav, hub.tui.Wizard.BACK) def test_settings_default_feeds_the_stop_and_exit_toggle(self): - # The Settings menu's "Default stop server and exit" value seeds the - # generate-form toggle (and so the run's stop-and-exit behavior). + # The Settings menu's "Stop server and exit" value decides the + # run's stop-and-exit behavior (it travels on the run kwargs). st = self._remote("faster", "faster-qwen3-tts", url="http://10.0.0.5:8000") with patch.object(hub.config, "STOP_SERVER_AND_EXIT", False): self._answer_form(backend="faster-remote", - faster_voice="obama", stop_and_exit=False) + faster_voice="obama") cmd = self._convert(None, [st]) self.assertIsNotNone(cmd) - self.assertFalse(self._field("stop_and_exit")["value"]) self.assertFalse(cmd[2]["stop_and_exit"]) def test_qwen_remote_limited_modes_and_api_url(self): @@ -1765,9 +1765,7 @@ class ConvertFlowTests(unittest.TestCase): [f["key"] for f in fields], ["backend", "model_id", "audiocpp_voice", "instructions", "request_options", "mode", "speaker", "clone", - "qwen_instructions", - "output_format", "language", "speed", - "single_file", "debug", "stop_and_exit"]) + "qwen_instructions", "single_file"]) # The form opens on the configured default (audio.cpp): its fields # show, the other backend's hide. Instructions shows too (optional # style/delivery control even on the clone-only higgs entry), while @@ -1776,15 +1774,12 @@ class ConvertFlowTests(unittest.TestCase): for key in ("model_id", "audiocpp_voice", "instructions"): self.assertTrue(self._field(key)["visible"](fields)) self.assertFalse(self._field("request_options")["visible"](fields)) - # Language shows for every backend except faster entries. - self.assertTrue(self._field("language")["visible"](fields)) for key in ("mode", "speaker", "clone", "qwen_instructions"): self.assertFalse(self._field(key)["visible"](fields)) # Picking qwen in the Backend field swaps which options show. fields[0]["value"] = "qwen" self.assertTrue(self._field("mode")["visible"](fields)) self.assertTrue(self._field("speaker")["visible"](fields)) - self.assertTrue(self._field("language")["visible"](fields)) self.assertFalse(self._field("clone")["visible"](fields)) # qwen's clone mode hides the speaker and shows the .wav path. self._field("mode")["value"] = "clone" @@ -2128,7 +2123,8 @@ class SettingsTests(unittest.TestCase): # Keys _apply_settings persists; every test that triggers a real or # fake config write restores these afterwards. _SETTING_KEYS = ("AUDIO_FORMAT", "AUDIO_BITRATE", "LANGUAGE", - "CHUNK_SIZE", "STOP_SERVER_AND_EXIT", + "CHUNK_SIZE", "INPUT_DIR", "OUTPUT_DIR", + "SPEED", "DEBUG", "STOP_SERVER_AND_EXIT", "AUDIOCPP_UNLOAD_MODELS", "QWEN_API_URL", "FASTER_API_URL", "AUDIOCPP_API_URL", @@ -2191,8 +2187,18 @@ class SettingsTests(unittest.TestCase): return True self._snapshot_settings() + # _apply_settings re-derives the converter module's folder + # globals; restore them afterwards. + original_folders = (hub.converter_mod.BOOKS_FOLDER, + hub.converter_mod.AUDIOBOOKS_FOLDER) + self.addCleanup(setattr, hub.converter_mod, "BOOKS_FOLDER", + original_folders[0]) + self.addCleanup(setattr, hub.converter_mod, "AUDIOBOOKS_FOLDER", + original_folders[1]) values = {"audio_format": "ogg", "audio_bitrate": " 192k ", "language": "en", "chunk_size": "300", + "input_dir": " /books ", "output_dir": "/audiobooks", + "speed": "1.5", "debug": True, "stop_and_exit": False, "unload_models": True, "qwen_port": "7862", @@ -2210,6 +2216,10 @@ class SettingsTests(unittest.TestCase): "AUDIO_BITRATE": "192k", "LANGUAGE": "English", "CHUNK_SIZE": 300, + "INPUT_DIR": "/books", + "OUTPUT_DIR": "/audiobooks", + "SPEED": 1.5, + "DEBUG": True, "STOP_SERVER_AND_EXIT": False, "AUDIOCPP_UNLOAD_MODELS": True, "QWEN_API_URL": "http://127.0.0.1:7862", @@ -2221,22 +2231,32 @@ class SettingsTests(unittest.TestCase): "http://10.0.0.6:8000", "AUDIOCPP_REMOTE_URL": "http://10.0.0.5:8080"}) - # In-memory config is reloaded so this session sees the change. + # In-memory config is reloaded so this session sees the change, + # and the converter module's folder globals follow the directories. self.assertEqual(hub.config.AUDIO_FORMAT, "ogg") self.assertEqual(hub.config.AUDIO_BITRATE, "192k") self.assertEqual(hub.config.LANGUAGE, "English") self.assertEqual(hub.config.CHUNK_SIZE, 300) + self.assertEqual(hub.config.INPUT_DIR, "/books") + self.assertEqual(hub.config.OUTPUT_DIR, "/audiobooks") + self.assertEqual(hub.config.SPEED, 1.5) + self.assertEqual(hub.config.DEBUG, True) self.assertEqual(hub.config.STOP_SERVER_AND_EXIT, False) self.assertEqual(hub.config.AUDIOCPP_UNLOAD_MODELS, True) self.assertEqual(hub.config.QWEN_API_URL, "http://127.0.0.1:7862") self.assertEqual(hub.config.FASTER_API_URL, "http://127.0.0.1:8001") self.assertEqual(hub.config.AUDIOCPP_REMOTE_URL, "http://10.0.0.5:8080") + self.assertEqual(hub.converter_mod.BOOKS_FOLDER, Path("/books")) + self.assertEqual(hub.converter_mod.AUDIOBOOKS_FOLDER, + Path("/audiobooks")) def test_apply_settings_rejects_bad_values(self): self._snapshot_settings() base = {"audio_format": "m4b", "audio_bitrate": "128k", "language": "English", "chunk_size": "250", + "input_dir": "./input", "output_dir": "./output", + "speed": "1.0", "debug": False, "stop_and_exit": True, "unload_models": True, "qwen_port": "7860", @@ -2247,6 +2267,14 @@ class SettingsTests(unittest.TestCase): with self.assertRaises(ValueError): hub._apply_settings({**base, "chunk_size": "0"}) with self.assertRaises(ValueError): + hub._apply_settings({**base, "speed": "0"}) + with self.assertRaises(ValueError): + hub._apply_settings({**base, "speed": "fast"}) + with self.assertRaises(ValueError): + hub._apply_settings({**base, "input_dir": " "}) + with self.assertRaises(ValueError): + hub._apply_settings({**base, "output_dir": ""}) + with self.assertRaises(ValueError): hub._apply_settings({**base, "audiocpp_port": "70000"}) with self.assertRaises(ValueError): hub._apply_settings({**base, @@ -2262,6 +2290,17 @@ class SettingsTests(unittest.TestCase): self.assertIsNone(hub._validate_chunk_size("250")) self.assertIsNotNone(hub._validate_chunk_size("abc")) self.assertIsNotNone(hub._validate_chunk_size("0")) + self.assertIsNone(hub._validate_speed("1.0")) + self.assertIsNone(hub._validate_speed("1.5")) + self.assertIsNone(hub._validate_speed(" 2 ")) + self.assertIsNotNone(hub._validate_speed("0")) + self.assertIsNotNone(hub._validate_speed("-1")) + self.assertIsNotNone(hub._validate_speed("fast")) + self.assertIsNotNone(hub._validate_speed("")) + self.assertIsNone(hub._validate_dir("./input")) + self.assertIsNone(hub._validate_dir(Path("/books"))) + self.assertIsNotNone(hub._validate_dir("")) + self.assertIsNotNone(hub._validate_dir(" ")) self.assertIsNone(hub._validate_port("8080")) self.assertIsNone(hub._validate_port("1")) self.assertIsNone(hub._validate_port("65535")) @@ -2270,9 +2309,9 @@ class SettingsTests(unittest.TestCase): self.assertIsNotNone(hub._validate_port("abc")) def test_language_fields_are_pickers_with_edit_hint(self): - # Both Language fields (Settings and Generate Audiobooks) are - # static pickers over the audio.cpp-menu languages, with a dim - # hint inside their edit dialog. Common languages lead. + # The Settings Language field is a static picker over the + # audio.cpp-menu languages, with a dim hint inside its edit + # dialog. Common languages lead. expected_choices = ["English", "Spanish", "Chinese", "French", "German", "Italian", "Portuguese", "Japanese", "Korean", "Russian", "Arabic", "Hindi", @@ -2284,19 +2323,34 @@ class SettingsTests(unittest.TestCase): fields = hub._settings_fields() field = next(f for f in fields if f["key"] == "language") - self.assertEqual(field["label"], "Default Language") + self.assertEqual(field["label"], "Language") self.assertEqual(field["kind"], "choice") self.assertEqual(field["choices"], expected_choices) self.assertEqual(field["help"], hint) self.assertEqual(field["value"], hub.config.LANGUAGE) - for gen_fields in (hub._common_fields(),): - field = next(f for f in gen_fields - if f["key"] == "language") - self.assertEqual(field["label"], "Language") - self.assertEqual(field["kind"], "choice") - self.assertEqual(field["choices"], expected_choices) - self.assertEqual(field["help"], hint) + def test_directory_fields_are_browsers(self): + # The Input/Output Directory settings use the DOS-style directory + # browser, seeded with the configured folder resolved against the + # project root. + fields = hub._settings_fields() + for key, config_name in (("input_dir", "INPUT_DIR"), + ("output_dir", "OUTPUT_DIR")): + field = next(f for f in fields if f["key"] == key) + self.assertEqual(field["kind"], "dir") + self.assertTrue(field["label"].endswith("Directory")) + self.assertEqual(field["value"], + hub.converter_mod.resolve_dir( + getattr(hub.config, config_name), + key.removesuffix("_dir"))) + self.assertIsNone(field["validate"](str(field["value"]))) + self.assertIsNotNone(field["validate"](" ")) + with patch.object(hub.config, "INPUT_DIR", "books"): + fields = hub._settings_fields() + field = next(f for f in fields if f["key"] == "input_dir") + self.assertEqual( + field["value"], + hub.converter_mod.BASE_DIR / "books") def test_settings_menu_builds_form_and_saves(self): captured = {} @@ -2305,6 +2359,8 @@ class SettingsTests(unittest.TestCase): captured["fields"] = fields return {"audio_format": "ogg", "audio_bitrate": "192k", "language": "English", "chunk_size": "300", + "input_dir": "/books", "output_dir": "/audiobooks", + "speed": "1.0", "debug": False, "stop_and_exit": True, "unload_models": True, "qwen_port": "7860", @@ -2324,13 +2380,19 @@ class SettingsTests(unittest.TestCase): hub._Hub(None).screen_settings() self.assertEqual([f["key"] for f in captured["fields"]], ["audio_format", "audio_bitrate", "language", - "chunk_size", "stop_and_exit", "unload_models", + "chunk_size", "input_dir", "output_dir", + "speed", "debug", "stop_and_exit", + "unload_models", "audiocpp_port", "faster_port", "qwen_port", "audiocpp_remote_url", "faster_remote_url", "qwen_remote_url"]) kinds = {f["key"]: f["kind"] for f in captured["fields"]} self.assertEqual(kinds["audio_format"], "choice") self.assertEqual(kinds["audio_bitrate"], "text") + self.assertEqual(kinds["input_dir"], "dir") + self.assertEqual(kinds["output_dir"], "dir") + self.assertEqual(kinds["speed"], "text") + self.assertEqual(kinds["debug"], "bool") self.assertEqual(kinds["audiocpp_port"], "text") self.assertEqual(kinds["stop_and_exit"], "bool") self.assertEqual(kinds["unload_models"], "bool") @@ -2339,22 +2401,32 @@ class SettingsTests(unittest.TestCase): self.assertEqual(labels["qwen_port"], "qwen-tts port") self.assertEqual(labels["audiocpp_remote_url"], "audio.cpp remote URL") + self.assertEqual(labels["input_dir"], "Input Directory") + self.assertEqual(labels["output_dir"], "Output Directory") self.assertNotIn("(clone)", " ".join(labels.values())) - # The language setting is a picker labelled "Default Language". - self.assertEqual(labels["language"], "Default Language") + # The language setting is a picker labelled "Language". + self.assertEqual(labels["language"], "Language") self.assertEqual(kinds["language"], "choice") # The ports section note hangs off the first port field, the remote # section note off the first remote URL field. notes = {f["key"]: f.get("note") for f in captured["fields"]} + self.assertTrue(notes["input_dir"]) + self.assertTrue(notes["output_dir"]) + self.assertTrue(notes["debug"]) self.assertTrue(notes["stop_and_exit"]) self.assertTrue(notes["audiocpp_port"]) self.assertTrue(notes["audiocpp_remote_url"]) self.assertIsNone(notes["audio_format"]) + self.assertIsNone(notes["speed"]) self.assertIsNone(notes["qwen_port"]) self.assertEqual(applied, [{"audio_format": "ogg", "audio_bitrate": "192k", "language": "English", "chunk_size": "300", + "input_dir": "/books", + "output_dir": "/audiobooks", + "speed": "1.0", + "debug": False, "stop_and_exit": True, "unload_models": True, "qwen_port": "7860", @@ -2468,6 +2540,8 @@ class SettingsTests(unittest.TestCase): return back_value # first exit: Esc return {"audio_format": "m4b", "audio_bitrate": "128k", "language": "English", "chunk_size": "250", + "input_dir": "./input", "output_dir": "./output", + "speed": "1.0", "debug": False, "stop_and_exit": True, "unload_models": True, "qwen_port": "7860", "faster_port": "8000", "audiocpp_port": "8080"} @@ -2499,7 +2573,8 @@ class SettingsTests(unittest.TestCase): original = {name: getattr(hub.config, name) for name in ("AUDIO_FORMAT", "AUDIO_BITRATE", "LANGUAGE", - "CHUNK_SIZE", "STOP_SERVER_AND_EXIT", + "CHUNK_SIZE", "INPUT_DIR", "OUTPUT_DIR", + "SPEED", "DEBUG", "STOP_SERVER_AND_EXIT", "AUDIOCPP_UNLOAD_MODELS", "QWEN_API_URL", "FASTER_API_URL", "AUDIOCPP_API_URL", @@ -2517,6 +2592,10 @@ class SettingsTests(unittest.TestCase): 'LANGUAGE = "English"\n' "\n" "CHUNK_SIZE = 250\n" + 'INPUT_DIR = "./input"\n' + 'OUTPUT_DIR = "./output"\n' + "SPEED = 1.0\n" + "DEBUG = False\n" "STOP_SERVER_AND_EXIT = True\n" "AUDIOCPP_UNLOAD_MODELS = True\n" 'QWEN_API_URL = "http://127.0.0.1:7860"\n' @@ -2538,6 +2617,11 @@ class SettingsTests(unittest.TestCase): text = path.read_text(encoding="utf-8") self.assertIn('AUDIO_FORMAT = "m4b"', text) self.assertIn("CHUNK_SIZE = 300", text) + # The settings-only fields are written back unchanged. + self.assertIn('INPUT_DIR = "', text) + self.assertIn('OUTPUT_DIR = "', text) + self.assertIn("SPEED = 1.0", text) + self.assertIn("DEBUG = False", text) # The running session also picked up the change in-memory. self.assertEqual(hub.config.CHUNK_SIZE, 300) |
