]> git.ipfire.org Git - thirdparty/starlette.git/commitdiff
Set encodings when reading config files (#2996)
authorsecrett2633 <65999962+secrett2633@users.noreply.github.com>
Sun, 26 Oct 2025 16:30:15 +0000 (01:30 +0900)
committerGitHub <noreply@github.com>
Sun, 26 Oct 2025 16:30:15 +0000 (16:30 +0000)
Co-authored-by: Marcelo Trylesinski <marcelotryle@gmail.com>
docs/config.md
starlette/config.py
tests/test_config.py

index d7faa281a9491cd4abdb5a970187c843daf968e8..25bc1de18898b0d2c0d8e43c49d94cb1a4addd6a 100644 (file)
@@ -120,6 +120,18 @@ DEBUG = config('DEBUG') # lookups APP_DEBUG, returns "yes"
 ENVIRONMENT = config('ENVIRONMENT') # lookups APP_ENVIRONMENT, raises KeyError as variable is not defined
 ```
 
+## Custom encoding for environment files 
+
+By default, Starlette reads environment files using UTF-8 encoding. 
+You can specify a different encoding by setting `encoding` argument.
+
+```python title="myproject/settings.py"
+from starlette.config import Config
+
+# Using custom encoding for .env file
+config = Config(".env", encoding="latin-1")
+```
+
 ## A full example
 
 Structuring large applications can be complex. You need proper separation of
index 091f857f3d98eb8acbe61d7f85d3a3f37f0b026c..7f839eebb073754bcac9cb3b4f2a5a7d0c3c5141 100644 (file)
@@ -52,6 +52,7 @@ class Config:
         env_file: str | Path | None = None,
         environ: Mapping[str, str] = environ,
         env_prefix: str = "",
+        encoding: str = "utf-8",
     ) -> None:
         self.environ = environ
         self.env_prefix = env_prefix
@@ -60,7 +61,7 @@ class Config:
             if not os.path.isfile(env_file):
                 warnings.warn(f"Config file '{env_file}' not found.")
             else:
-                self.file_values = self._read_file(env_file)
+                self.file_values = self._read_file(env_file, encoding)
 
     @overload
     def __call__(self, key: str, *, default: None) -> str | None: ...
@@ -107,9 +108,9 @@ class Config:
             return self._perform_cast(key, default, cast)
         raise KeyError(f"Config '{key}' is missing, and has no default.")
 
-    def _read_file(self, file_name: str | Path) -> dict[str, str]:
+    def _read_file(self, file_name: str | Path, encoding: str) -> dict[str, str]:
         file_values: dict[str, str] = {}
-        with open(file_name) as input_file:
+        with open(file_name, encoding=encoding) as input_file:
             for line in input_file.readlines():
                 line = line.strip()
                 if "=" in line and not line.startswith("#"):
index c256ffc681503164aef464bdf1c8357c6ced653d..c15b6727ed323d0ba8ab1bc3046f44a467712ba4 100644 (file)
@@ -140,3 +140,10 @@ def test_config_with_env_prefix(tmpdir: Path, monkeypatch: pytest.MonkeyPatch) -
 
     with pytest.raises(KeyError):
         config.get("ENVIRONMENT")
+
+
+def test_config_with_encoding(tmpdir: Path) -> None:
+    path = tmpdir / ".env"
+    path.write_text("MESSAGE=Hello 世界\n", encoding="utf-8")
+    config = Config(path, encoding="utf-8")
+    assert config.get("MESSAGE") == "Hello 世界"