From b158aa721cdf625c72f79f3583e5cc1f0cea2950 Mon Sep 17 00:00:00 2001 From: Bertrand Bonnefoy-Claudet Date: Wed, 10 Mar 2021 22:36:01 +0100 Subject: [PATCH] Use UTF-8 as default encoding The default value for the `encoding` paramter of `load_dotenv` and `dotenv_values` is now `"utf-8"` instead of `None` (which selected the encoding based on the user's locale). It is passed directly to `io.open`. The rationale for this change is that the encoding of a project file like `.env` should not depend on the user's locale by default. UTF-8 makes sense as the default encoding since it is also used for Python source files. The main drawback is that it departs from `open`'s default value of `None` for the `encoding` parameter. The default value of `None` was a source of confusion for some users. The Flask and Docker Compose projects already use `encoding="utf-8"` to enforce the use of UTF-8 and avoid that sort of confusion. This is a breaking change but only for users with a non-UTF-8 locale and non-UTF-8 characters in their .env files. --- CHANGELOG.md | 6 ++++- src/dotenv/main.py | 61 ++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 56 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index effa2510..1db10901 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,11 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] -- Fix resolution order in variable expansion with `override=False` (#? by [@bbc2]). +### Changed + +- The default value of the `encoding` parameter for `load_dotenv` and `dotenv_values` is + now `"utf-8"` instead of `None` (#? by [@bbc2]). +- Fix resolution order in variable expansion with `override=False` (#287 by [@bbc2]). ## [0.15.0] - 2020-10-28 diff --git a/src/dotenv/main.py b/src/dotenv/main.py index 31c41ee7..16f22d2c 100644 --- a/src/dotenv/main.py +++ b/src/dotenv/main.py @@ -293,22 +293,63 @@ def _is_interactive(): return '' -def load_dotenv(dotenv_path=None, stream=None, verbose=False, override=False, interpolate=True, **kwargs): - # type: (Union[Text, _PathLike, None], Optional[_StringIO], bool, bool, bool, Union[None, Text]) -> bool +def load_dotenv( + dotenv_path=None, + stream=None, + verbose=False, + override=False, + interpolate=True, + encoding="utf-8", +): + # type: (Union[Text, _PathLike, None], Optional[_StringIO], bool, bool, bool, Optional[Text]) -> bool # noqa """Parse a .env file and then load all the variables found as environment variables. - *dotenv_path*: absolute or relative path to .env file. - - *stream*: `StringIO` object with .env content. - - *verbose*: whether to output the warnings related to missing .env file etc. Defaults to `False`. - - *override*: where to override the system environment variables with the variables in `.env` file. - Defaults to `False`. + - *stream*: `StringIO` object with .env content, used if `dotenv_path` is `None`. + - *verbose*: whether to output a warning the .env file is missing. Defaults to + `False`. + - *override*: whether to override the system environment variables with the variables + in `.env` file. Defaults to `False`. + - *encoding*: encoding to be used to read the file. + + If both `dotenv_path` and `stream`, `find_dotenv()` is used to find the .env file. """ f = dotenv_path or stream or find_dotenv() - dotenv = DotEnv(f, verbose=verbose, interpolate=interpolate, override=override, **kwargs) + dotenv = DotEnv( + f, + verbose=verbose, + interpolate=interpolate, + override=override, + encoding=encoding, + ) return dotenv.set_as_environment_variables() -def dotenv_values(dotenv_path=None, stream=None, verbose=False, interpolate=True, **kwargs): - # type: (Union[Text, _PathLike, None], Optional[_StringIO], bool, bool, Union[None, Text]) -> Dict[Text, Optional[Text]] # noqa: E501 +def dotenv_values( + dotenv_path=None, + stream=None, + verbose=False, + interpolate=True, + encoding="utf-8", +): + # type: (Union[Text, _PathLike, None], Optional[_StringIO], bool, bool, Optional[Text]) -> Dict[Text, Optional[Text]] # noqa: E501 + """ + Parse a .env file and return its content as a dict. + + - *dotenv_path*: absolute or relative path to .env file. + - *stream*: `StringIO` object with .env content, used if `dotenv_path` is `None`. + - *verbose*: whether to output a warning the .env file is missing. Defaults to + `False`. + in `.env` file. Defaults to `False`. + - *encoding*: encoding to be used to read the file. + + If both `dotenv_path` and `stream`, `find_dotenv()` is used to find the .env file. + """ f = dotenv_path or stream or find_dotenv() - return DotEnv(f, verbose=verbose, interpolate=interpolate, override=True, **kwargs).dict() + return DotEnv( + f, + verbose=verbose, + interpolate=interpolate, + override=True, + encoding=encoding, + ).dict()