mirror of
https://github.com/p-e-w/heretic.git
synced 2026-11-06 05:16:39 +00:00
feat: allow specifying a custom config file path (#557)
This commit is contained in:
1 parent
4b3a1bd8fd
commit
f4cf535403
3 files changed
+66
-2
No files matched your search
@@ -85,7 +85,9 @@ Replace `Qwen/Qwen3-4B-Instruct-2507` with whatever model you want to process.
|
||||
**By default, Heretic performs censorship removal (refusal suppression).**
|
||||
If you want to do something else, choose one of the configuration files linked
|
||||
above, or write your own. See [`config.default.toml`](/config.default.toml)
|
||||
for available configuration options.
|
||||
for available configuration options. Heretic loads the configuration from
|
||||
`config.toml` in the working directory by default, or from the file path in the
|
||||
`HERETIC_CONFIG_FILE` environment variable.
|
||||
|
||||
> [!IMPORTANT]
|
||||
>
|
||||
|
||||
+11
-1
@@ -1,6 +1,7 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (C) 2025-2026 Philipp Emanuel Weidmann <pew@worldwidemann.com> + contributors
|
||||
|
||||
import os
|
||||
from enum import Enum
|
||||
from typing import Any, Literal, TypeAlias
|
||||
|
||||
@@ -190,6 +191,15 @@ class BenchmarkSpecification(BaseModel):
|
||||
)
|
||||
|
||||
|
||||
def _config_path() -> str:
|
||||
path = os.environ.get("HERETIC_CONFIG_FILE", "config.toml")
|
||||
|
||||
if "HERETIC_CONFIG_FILE" in os.environ and not os.path.isfile(path):
|
||||
raise SystemExit(f"heretic: configuration file {path} does not exist")
|
||||
|
||||
return path
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
model: str = Field(description="Hugging Face model ID, or path to model on disk.")
|
||||
|
||||
@@ -590,7 +600,7 @@ class Settings(BaseSettings):
|
||||
EnvSettingsSource(settings_cls, env_prefix="HERETIC_"),
|
||||
dotenv_settings,
|
||||
file_secret_settings,
|
||||
TomlConfigSettingsSource(settings_cls, toml_file="config.toml"),
|
||||
TomlConfigSettingsSource(settings_cls, toml_file=_config_path()),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -134,6 +134,58 @@ class ModelValidateInitOnlyTests(unittest.TestCase):
|
||||
self.assertEqual(settings.max_memory, {"0": "20GiB"})
|
||||
|
||||
|
||||
class ConfigFileSelectionTests(unittest.TestCase):
|
||||
def settings(
|
||||
self, config_files: dict[str, str], heretic_config: str | None = None
|
||||
) -> Settings:
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
for name, content in config_files.items():
|
||||
Path(directory, name).write_text(content)
|
||||
|
||||
environment = {
|
||||
key: value
|
||||
for key, value in os.environ.items()
|
||||
if not key.startswith("HERETIC_")
|
||||
}
|
||||
if heretic_config is not None:
|
||||
environment["HERETIC_CONFIG_FILE"] = heretic_config
|
||||
|
||||
previous_directory = os.getcwd()
|
||||
os.chdir(directory)
|
||||
try:
|
||||
with (
|
||||
patch.dict(os.environ, environment, clear=True),
|
||||
patch("sys.argv", ["heretic"]),
|
||||
):
|
||||
return Settings(model="dummy")
|
||||
finally:
|
||||
os.chdir(previous_directory)
|
||||
|
||||
def test_environment_variable_selects_file(self) -> None:
|
||||
settings = self.settings({"custom.toml": "n_trials = 42\n"}, "custom.toml")
|
||||
|
||||
self.assertEqual(settings.n_trials, 42)
|
||||
|
||||
def test_default_config_toml_still_loaded(self) -> None:
|
||||
settings = self.settings({"config.toml": "n_trials = 42\n"})
|
||||
|
||||
self.assertEqual(settings.n_trials, 42)
|
||||
|
||||
def test_missing_default_config_file_is_silent(self) -> None:
|
||||
settings = self.settings({})
|
||||
|
||||
self.assertEqual(settings.n_trials, Settings.model_fields["n_trials"].default)
|
||||
|
||||
def test_missing_configured_file_aborts(self) -> None:
|
||||
with self.assertRaisesRegex(SystemExit, "does not exist"):
|
||||
self.settings({}, "missing.toml")
|
||||
|
||||
def test_configured_default_file_missing_aborts(self) -> None:
|
||||
# Unlike a missing implicit default, this counts as a configuration error.
|
||||
with self.assertRaisesRegex(SystemExit, "does not exist"):
|
||||
self.settings({}, "config.toml")
|
||||
|
||||
|
||||
class SettingsUploadTagsTests(unittest.TestCase):
|
||||
def test_default_upload_tags(self) -> None:
|
||||
with patch("sys.argv", ["heretic"]):
|
||||
|
||||
Reference in new issue
Block a user